void run() {
     IndexDescriptor* id = addIndexWithInfo();
     // Create a SortPhaseOne.
     SortPhaseOne phaseOne;
     phaseOne.sorter.reset( new BSONObjExternalSorter(_aFirstSort));
     // Add index keys to the phaseOne.
     int32_t nKeys = 130;
     for( int32_t i = 0; i < nKeys; ++i ) {
         phaseOne.sorter->add( BSON( "a" << i ), /* dummy disk loc */ DiskLoc(), false );
     }
     phaseOne.nkeys = phaseOne.n = nKeys;
     phaseOne.sorter->sort( false );
     // Set up remaining arguments.
     set<DiskLoc> dups;
     CurOp* op = cc().curop();
     ProgressMeterHolder pm (op->setMessage("BuildBottomUp",
                                            "BuildBottomUp Progress",
                                            nKeys,
                                            nKeys));
     pm.finished();
     Timer timer;
     // The index's root has not yet been set.
     ASSERT( id->getHead().isNull() );
     // Finish building the index.
     buildBottomUpPhases2And3<V1>( true,
                                   id,
                                   *phaseOne.sorter,
                                   false,
                                   dups,
                                   op,
                                   &phaseOne,
                                   pm,
                                   timer,
                                   true );
     // The index's root is set after the build is complete.
     ASSERT( !id->getHead().isNull() );
     // Create a cursor over the index.
     scoped_ptr<BtreeCursor> cursor(
             BtreeCursor::make( nsdetails( _ns ),
                                id->getOnDisk(),
                                BSON( "" << -1 ),    // startKey below minimum key.
                                BSON( "" << nKeys ), // endKey above maximum key.
                                true,                // endKeyInclusive true.
                                1                    // direction forward.
                                ) );
     // Check that the keys in the index are the expected ones.
     int32_t expectedKey = 0;
     for( ; cursor->ok(); cursor->advance(), ++expectedKey ) {
         ASSERT_EQUALS( expectedKey, cursor->currKey().firstElement().number() );
     }
     ASSERT_EQUALS( nKeys, expectedKey );
 }
Exemple #2
0
    void profile(OperationContext* txn, const Client& c, int op, CurOp& currentOp) {
        // initialize with 1kb to start, to avoid realloc later
        // doing this outside the dblock to improve performance
        BufBuilder profileBufBuilder(1024);

        bool tryAgain = false;
        while ( 1 ) {
            try {
                // NOTE: It's kind of weird that we lock the op's namespace, but have to for now
                // since we're sometimes inside the lock already
                const string dbname(nsToDatabase(currentOp.getNS()));
                scoped_ptr<Lock::DBLock> lk;

                // todo: this can be slow, perhaps can re-work
                if ( !txn->lockState()->isDbLockedForMode( dbname, MODE_IX ) ) {
                    lk.reset( new Lock::DBLock( txn->lockState(),
                                                dbname,
                                                tryAgain ? MODE_X : MODE_IX) );
                }
                Database* db = dbHolder().get(txn, dbname);
                if (db != NULL) {
                    // We want the profiling to happen in a different WUOW from the actual op.
                    Lock::CollectionLock clk(txn->lockState(), db->getProfilingNS(), MODE_X);
                    WriteUnitOfWork wunit(txn);
                    Client::Context cx(txn, currentOp.getNS(), false);
                    if ( !_profile(txn, c, cx.db(), currentOp, profileBufBuilder ) && lk.get() ) {
                        if ( tryAgain ) {
                            // we couldn't profile, but that's ok, we should have logged already
                            break;
                        }
                        // we took an IX lock, so now we try again with an X lock
                        tryAgain = true;
                        continue;
                    }
                    wunit.commit();
                }
                else {
                    mongo::log() << "note: not profiling because db went away - "
                                 << "probably a close on: " << currentOp.getNS();
                }
                return;
            }
            catch (const AssertionException& assertionEx) {
                warning() << "Caught Assertion while trying to profile " << opToString(op)
                          << " against " << currentOp.getNS()
                          << ": " << assertionEx.toString() << endl;
                return;
            }
        }
    }
Exemple #3
0
    bool receivedGetMore(DbResponse& dbresponse, Message& m, CurOp& curop ) {
        bool ok = true;

        DbMessage d(m);

        const char *ns = d.getns();
        int ntoreturn = d.pullInt();
        long long cursorid = d.pullInt64();

        curop.debug().ns = ns;
        curop.debug().ntoreturn = ntoreturn;
        curop.debug().cursorid = cursorid;

        time_t start = 0;
        int pass = 0;
        bool exhaust = false;
        QueryResult* msgdata;
        while( 1 ) {
            try {
                readlock lk;
                Client::Context ctx(ns);
                msgdata = processGetMore(ns, ntoreturn, cursorid, curop, pass, exhaust);
            }
            catch ( AssertionException& e ) {
                exhaust = false;
                curop.debug().exceptionInfo = e.getInfo();
                msgdata = emptyMoreResult(cursorid);
                ok = false;
            }
            if (msgdata == 0) {
                exhaust = false;
                massert(13073, "shutting down", !inShutdown() );
                if( pass == 0 ) {
                    start = time(0);
                }
                else {
                    if( time(0) - start >= 4 ) {
                        // after about 4 seconds, return.  this is a sanity check.  pass stops at 1000 normally
                        // for DEV this helps and also if sleep is highly inaccurate on a platform.  we want to
                        // return occasionally so slave can checkpoint.
                        pass = 10000;
                    }
                }
                pass++;
                DEV
                sleepmillis(20);
                else
                    sleepmillis(2);
                continue;
            }
Exemple #4
0
 std::vector<BSONObj> IndexBuilder::killMatchingIndexBuilds(const BSONObj& criteria) {
     verify(Lock::somethingWriteLocked());
     std::vector<BSONObj> indexes;
     CurOp* op = NULL;
     while ((op = CurOp::getOp(criteria)) != NULL) {
         BSONObj index = op->query();
         killCurrentOp.kill(op->opNum());
         indexes.push_back(index);
     }
     if (indexes.size() > 0) {
         log() << "halted " << indexes.size() << " index build(s)" << endl;
     }
     return indexes;
 }
Exemple #5
0
    void ClientCursor::staticYield(int micros, const StringData& ns) {
        bool haveReadLock = Lock::isReadLocked();

        killCurrentOp.checkForInterrupt();
        {
            dbtempreleasecond unlock;
            if ( unlock.unlocked() ) {
                if ( haveReadLock ) {
                    // This sleep helps reader threads yield to writer threads.
                    // Without this, the underlying reader/writer lock implementations
                    // are not sufficiently writer-greedy.
#ifdef _WIN32
                    SwitchToThread();
#else
                    if ( micros == 0 ) {
                        yieldOrSleepFor1Microsecond();
                    }
                    else {
                        sleepmicros(1);
                    }
#endif
                }
                else {
                    if ( micros == -1 ) {
                        sleepmicros(Client::recommendedYieldMicros());
                    }
                    else if ( micros == 0 ) {
                        yieldOrSleepFor1Microsecond();
                    }
                    else if ( micros > 0 ) {
                        sleepmicros( micros );
                    }
                }

            }
            else if ( Listener::getTimeTracker() == 0 ) {
                // we aren't running a server, so likely a repair, so don't complain
            }
            else {
                CurOp * c = cc().curop();
                while ( c->parent() )
                    c = c->parent();
                warning() << "ClientCursor::staticYield can't unlock b/c of recursive lock"
                          << " ns: " << ns 
                          << " top: " << c->info()
                          << endl;
            }
        }
    }
void MoveTimingHelper::done(int step) {
    invariant(step == ++_nextStep);
    invariant(step <= _totalNumSteps);

    const std::string s = str::stream() << "step " << step << " of " << _totalNumSteps;

    CurOp* op = CurOp::get(_txn);

    {
        stdx::lock_guard<Client> lk(*_txn->getClient());
        op->setMessage_inlock(s.c_str());
    }

    _b.appendNumber(s, _t.millis());
    _t.reset();
}
Exemple #7
0
    void profile( const Client& c , CurOp& currentOp ) {
        assertInWriteLock();

        Database *db = c.database();
        DEV assert( db );
        const char *ns = db->profileName.c_str();
        
        // build object
        profileBufBuilder.reset();
        BSONObjBuilder b(profileBufBuilder);
        b.appendDate("ts", jsTime());
        currentOp.debug().append( b );

        b.append("client", c.clientAddress() );

        if ( c.getAuthenticationInfo() )
            b.append( "user" , c.getAuthenticationInfo()->getUser( nsToDatabase( ns ) ) );

        BSONObj p = b.done();

        // write: not replicated
        NamespaceDetails *d = db->namespaceIndex.details(ns);
        if( d ) {
            int len = p.objsize();
            Record *r = theDataFileMgr.fast_oplog_insert(d, ns, len);
            memcpy(getDur().writingPtr(r->data, len), p.objdata(), len);
        }
        else { 
            static time_t last;
            if( time(0) > last+10 ) {
                log() << "profile: warning ns " << ns << " does not exist" << endl;
                last = time(0);
            }
        }
    }
Exemple #8
0
    void receivedUpdate(Message& m, CurOp& op) {
        DbMessage d(m);
        const char *ns = d.getns();
        op.debug().ns = ns;
        int flags = d.pullInt();
        BSONObj query = d.nextJsObj();

        verify( d.moreJSObjs() );
        verify( query.objsize() < m.header()->dataLen() );
        BSONObj toupdate = d.nextJsObj();
        uassert( 10055 , "update object too large", toupdate.objsize() <= BSONObjMaxUserSize);
        verify( toupdate.objsize() < m.header()->dataLen() );
        verify( query.objsize() + toupdate.objsize() < m.header()->dataLen() );
        bool upsert = flags & UpdateOption_Upsert;
        bool multi = flags & UpdateOption_Multi;
        bool broadcast = flags & UpdateOption_Broadcast;

        Status status = cc().getAuthorizationManager()->checkAuthForUpdate(ns, upsert);
        uassert(16538, status.reason(), status.isOK());

        op.debug().query = query;
        op.setQuery(query);

        PageFaultRetryableSection s;
        while ( 1 ) {
            try {
                Lock::DBWrite lk(ns);
                
                // void ReplSetImpl::relinquish() uses big write lock so 
                // this is thus synchronized given our lock above.
                uassert( 10054 ,  "not master", isMasterNs( ns ) );
                
                // if this ever moves to outside of lock, need to adjust check Client::Context::_finishInit
                if ( ! broadcast && handlePossibleShardedMessage( m , 0 ) )
                    return;
                
                Client::Context ctx( ns );
                
                UpdateResult res = updateObjects(ns, toupdate, query, upsert, multi, true, op.debug() );
                lastError.getSafe()->recordUpdate( res.existing , res.num , res.upserted ); // for getlasterror
                break;
            }
            catch ( PageFaultException& e ) {
                e.touch();
            }
        }
    }
Exemple #9
0
    void inProgCmd( Message &m, DbResponse &dbresponse ) {
        BSONObjBuilder b;

        if (!cc().getAuthorizationManager()->checkAuthorization(
                AuthorizationManager::SERVER_RESOURCE_NAME, ActionType::inprog)) {
            b.append("err", "unauthorized");
        }
        else {
            DbMessage d(m);
            QueryMessage q(d);
            bool all = q.query["$all"].trueValue();
            bool allMatching = q.query["$allMatching"].trueValue();
            vector<BSONObj> vals;
            BSONObjBuilder qb;
            for (BSONObjIterator it(q.query); it.more(); ) {
                BSONElement e = it.next();
                StringData fn(e.fieldName());
                if (fn != "$all" && fn != "$allMatching") {
                    qb.append(e);
                }
            }
            {
                Client& me = cc();
                scoped_lock bl(Client::clientsMutex);
                scoped_ptr<Matcher> m(new Matcher(qb.done()));
                for( set<Client*>::iterator i = Client::clients.begin(); i != Client::clients.end(); i++ ) {
                    Client *c = *i;
                    verify( c );
                    CurOp* co = c->curop();
                    if ( c == &me && !co ) {
                        continue;
                    }
                    verify( co );
                    if( all || allMatching || co->displayInCurop() ) {
                        BSONObj info = co->info();
                        if ( all || m->matches( info )) {
                            vals.push_back( info );
                        }
                    }
                }
            }
            b.append("inprog", vals);
        }

        replyToQuery(0, m, dbresponse, b.obj());
    }
    bool GlobalEnvironmentMongoD::killOperation(AtomicUInt opId) {
        scoped_lock clientLock(Client::clientsMutex);
        bool found = false;

        // XXX clean up
        {
            for( set< Client* >::const_iterator j = Client::clients.begin();
                 !found && j != Client::clients.end();
                 ++j ) {

                for( CurOp *k = ( *j )->curop(); !found && k; k = k->parent() ) {
                    if ( k->opNum() != opId )
                        continue;

                    k->kill();
                    for( CurOp *l = ( *j )->curop(); l; l = l->parent() ) {
                        l->kill();
                    }

                    found = true;
                }
            }
        }
        if ( found ) {
            interruptJs( &opId );
        }
        return found;
    }
Exemple #11
0
    void receivedUpdate(Message& m, CurOp& op) {
        DbMessage d(m);
        const char *ns = d.getns();
        op.debug().ns = ns;
        int flags = d.pullInt();
        BSONObj query = d.nextJsObj();

        verify(d.moreJSObjs());
        verify(query.objsize() < m.header()->dataLen());
        const BSONObj updateobj = d.nextJsObj();
        uassert(10055, "update object too large", updateobj.objsize() <= BSONObjMaxUserSize);
        verify(updateobj.objsize() < m.header()->dataLen());
        verify(query.objsize() + updateobj.objsize() < m.header()->dataLen());

        op.debug().query = query;
        op.debug().updateobj = updateobj;
        op.setQuery(query);

        const bool upsert = flags & UpdateOption_Upsert;
        const bool multi = flags & UpdateOption_Multi;
        const bool broadcast = flags & UpdateOption_Broadcast;

        Status status = cc().getAuthorizationManager()->checkAuthForUpdate(ns, upsert);
        uassert(16538, status.reason(), status.isOK());

        OpSettings settings;
        settings.setQueryCursorMode(WRITE_LOCK_CURSOR);
        settings.setJustOne(!multi);
        cc().setOpSettings(settings);

        Client::ShardedOperationScope sc;
        if (!broadcast && sc.handlePossibleShardedMessage(m, 0)) {
            return;
        }

        LOCK_REASON(lockReason, "update");
        try {
            Lock::DBRead lk(ns, lockReason);
            lockedReceivedUpdate(ns, m, op, updateobj, query, upsert, multi);
        }
        catch (RetryWithWriteLock &e) {
            Lock::DBWrite lk(ns, lockReason);
            lockedReceivedUpdate(ns, m, op, updateobj, query, upsert, multi);
        }
    }
Exemple #12
0
    bool KillCurrentOp::_killImpl_inclientlock(AtomicUInt i, bool* pNotifyFlag /* = NULL */) {
        bool found = false;
        {
            for( set< Client* >::const_iterator j = Client::clients.begin();
                 !found && j != Client::clients.end();
                 ++j ) {

                for( CurOp *k = ( *j )->curop(); !found && k; k = k->parent() ) {
                    if ( k->opNum() != i )
                        continue;

                    k->kill(pNotifyFlag);
                    for( CurOp *l = ( *j )->curop(); l; l = l->parent() ) {
                        l->kill();
                    }

                    found = true;
                }
            }
        }
        if ( found ) {
            interruptJs( &i );
        }
        return found;
    }
    Status OperationContextImpl::checkForInterruptNoAssert() const {
        if (getGlobalServiceContext()->getKillAllOperations()) {
            return Status(ErrorCodes::InterruptedAtShutdown, "interrupted at shutdown");
        }

        CurOp* curOp = CurOp::get(this);
        if (curOp->maxTimeHasExpired()) {
            curOp->kill();
            return Status(ErrorCodes::ExceededTimeLimit, "operation exceeded time limit");
        }

        MONGO_FAIL_POINT_BLOCK(checkForInterruptFail, scopedFailPoint) {
            if (opShouldFail(this, scopedFailPoint.getData())) {
                log() << "set pending kill on "
                      << (curOp->parent() ? "nested" : "top-level")
                      << " op " << curOp->opNum() << ", for checkForInterruptFail";
                curOp->kill();
            }
        }

        if (curOp->killPending()) {
            return Status(ErrorCodes::Interrupted, "operation was interrupted");
        }

        return Status::OK();
    }
Exemple #14
0
    void receivedDelete(Message& m, CurOp& op) {
        DbMessage d(m);
        const char *ns = d.getns();

        Status status = cc().getAuthorizationManager()->checkAuthForDelete(ns);
        uassert(16542, status.reason(), status.isOK());

        op.debug().ns = ns;
        int flags = d.pullInt();
        verify(d.moreJSObjs());
        BSONObj pattern = d.nextJsObj();

        op.debug().query = pattern;
        op.setQuery(pattern);

        const bool justOne = flags & RemoveOption_JustOne;
        const bool broadcast = flags & RemoveOption_Broadcast;

        OpSettings settings;
        settings.setQueryCursorMode(WRITE_LOCK_CURSOR);
        settings.setJustOne(justOne);
        cc().setOpSettings(settings);

        Client::ShardedOperationScope sc;
        if (!broadcast && sc.handlePossibleShardedMessage(m, 0)) {
            return;
        }

        LOCK_REASON(lockReason, "delete");
        Lock::DBRead lk(ns, lockReason);

        // writelock is used to synchronize stepdowns w/ writes
        uassert(10056, "not master", isMasterNs(ns));

        Client::Context ctx(ns);
        long long n;
        scoped_ptr<Client::AlternateTransactionStack> altStack(opNeedsAltTxn(ns) ? new Client::AlternateTransactionStack : NULL);
        Client::Transaction transaction(DB_SERIALIZABLE);
        n = deleteObjects(ns, pattern, justOne, true);
        transaction.commit();

        lastError.getSafe()->recordDelete( n );
        op.debug().ndeleted = n;
    }
Exemple #15
0
    void ClientCursor::staticYield( int micros , const StringData& ns , Record * rec ) {
        bool haveReadLock = Lock::isReadLocked();

        killCurrentOp.checkForInterrupt( false );
        {
            auto_ptr<LockMongoFilesShared> lk;
            if ( rec ) {
                // need to lock this else rec->touch won't be safe file could disappear
                lk.reset( new LockMongoFilesShared() );
            }
            
            dbtempreleasecond unlock;
            if ( unlock.unlocked() ) {
                if ( haveReadLock ) {
                    // don't sleep with a read lock
                }
                else {
                    if ( micros == -1 )
                        micros = Client::recommendedYieldMicros();
                    if ( micros > 0 )
                        sleepmicros( micros );
                }
                
            }
            else if ( Listener::getTimeTracker() == 0 ) {
                // we aren't running a server, so likely a repair, so don't complain
            }
            else {
                CurOp * c = cc().curop();
                while ( c->parent() )
                    c = c->parent();
                warning() << "ClientCursor::yield can't unlock b/c of recursive lock"
                          << " ns: " << ns 
                          << " top: " << c->info()
                          << endl;
            }

            if ( rec )
                rec->touch();

            lk.reset(0); // need to release this before dbtempreleasecond
        }
    }
Exemple #16
0
    void receivedDelete(Message& m, CurOp& op) {
        DbMessage d(m);
        const char *ns = d.getns();

        Status status = cc().getAuthorizationManager()->checkAuthForDelete(ns);
        uassert(16542, status.reason(), status.isOK());

        op.debug().ns = ns;
        int flags = d.pullInt();
        bool justOne = flags & RemoveOption_JustOne;
        bool broadcast = flags & RemoveOption_Broadcast;
        verify( d.moreJSObjs() );
        BSONObj pattern = d.nextJsObj();
        
        op.debug().query = pattern;
        op.setQuery(pattern);

        PageFaultRetryableSection s;
        while ( 1 ) {
            try {
                Lock::DBWrite lk(ns);
                
                // writelock is used to synchronize stepdowns w/ writes
                uassert( 10056 ,  "not master", isMasterNs( ns ) );
                
                // if this ever moves to outside of lock, need to adjust check Client::Context::_finishInit
                if ( ! broadcast && handlePossibleShardedMessage( m , 0 ) )
                    return;
                
                Client::Context ctx(ns);
                
                long long n = deleteObjects(ns, pattern, justOne, true);
                lastError.getSafe()->recordDelete( n );
                op.debug().ndeleted = n;
                break;
            }
            catch ( PageFaultException& e ) {
                LOG(2) << "recordDelete got a PageFaultException" << endl;
                e.touch();
            }
        }
    }
Exemple #17
0
    /**
     * @return if collection existed or was created
     */
    static bool _profile(OperationContext* txn,
                         const Client& c,
                         Database* db,
                         CurOp& currentOp,
                         BufBuilder& profileBufBuilder) {
        dassert( db );

        // build object
        BSONObjBuilder b(profileBufBuilder);

        const bool isQueryObjTooBig = !currentOp.debug().append(currentOp, b,
                MAX_PROFILE_DOC_SIZE_BYTES);

        b.appendDate("ts", jsTime());
        b.append("client", c.clientAddress());

        AuthorizationSession * authSession = c.getAuthorizationSession();
        _appendUserInfo(currentOp, b, authSession);

        BSONObj p = b.done();

        if (static_cast<size_t>(p.objsize()) > MAX_PROFILE_DOC_SIZE_BYTES || isQueryObjTooBig) {
            string small = p.toString(/*isArray*/false, /*full*/false);

            warning() << "can't add full line to system.profile: " << small << endl;

            // rebuild with limited info
            BSONObjBuilder b(profileBufBuilder);
            b.appendDate("ts", jsTime());
            b.append("client", c.clientAddress() );
            _appendUserInfo(currentOp, b, authSession);

            b.append("err", "profile line too large (max is 100KB)");

            // should be much smaller but if not don't break anything
            if (small.size() < MAX_PROFILE_DOC_SIZE_BYTES){
                b.append("abbreviated", small);
            }

            p = b.done();
        }

        WriteUnitOfWork wunit(txn);

        // write: not replicated
        // get or create the profiling collection
        Collection* profileCollection = getOrCreateProfileCollection(txn, db);
        if ( !profileCollection ) {
            return false;
        }
        profileCollection->insertDocument( txn, p, false );
        wunit.commit();
        return true;
    }
Exemple #18
0
    void receivedInsert(Message& m, CurOp& op) {
        DbMessage d(m);
        const char *ns = d.getns();
        op.debug().ns = ns;

        StringData coll = nsToCollectionSubstring(ns);
        // Auth checking for index writes happens later.
        if (coll != "system.indexes") {
            Status status = cc().getAuthorizationManager()->checkAuthForInsert(ns);
            uassert(16544, status.reason(), status.isOK());
        }

        if (!d.moreJSObjs()) {
            // strange.  should we complain?
            return;
        }

        vector<BSONObj> objs;
        while (d.moreJSObjs()) {
            objs.push_back(d.nextJsObj());
        }

        const bool keepGoing = d.reservedField() & InsertOption_ContinueOnError;

        OpSettings settings;
        settings.setQueryCursorMode(WRITE_LOCK_CURSOR);
        cc().setOpSettings(settings);

        if (coll == "system.indexes" &&
                // Can only build non-unique indexes in the background, because the
                // hot indexer does not know how to perform unique checks.
                objs[0]["background"].trueValue() && !objs[0]["unique"].trueValue()) {
            _buildHotIndex(ns, m, objs);
            return;
        }

        scoped_ptr<Client::ShardedOperationScope> scp;
        if (coll != "system.indexes") {
            scp.reset(new Client::ShardedOperationScope);
            if (scp->handlePossibleShardedMessage(m, 0)) {
                return;
            }
        }

        LOCK_REASON(lockReason, "insert");
        try {
            Lock::DBRead lk(ns, lockReason);
            lockedReceivedInsert(ns, m, objs, op, keepGoing);
        }
        catch (RetryWithWriteLock &e) {
            Lock::DBWrite lk(ns, lockReason);
            lockedReceivedInsert(ns, m, objs, op, keepGoing);
        }
    }
Exemple #19
0
    void profile( const Client& c , CurOp& currentOp ) {
        verify( Lock::somethingWriteLocked() );

        Database *db = c.database();
        DEV verify( db );
        const char *ns = db->profileName.c_str();
        
        // build object
        profileBufBuilder.reset();
        BSONObjBuilder b(profileBufBuilder);

        const bool isQueryObjTooBig = !currentOp.debug().append(currentOp, b,
                MAX_PROFILE_DOC_SIZE_BYTES);

        b.appendDate("ts", jsTime());
        b.append("client", c.clientAddress());

        if (c.getAuthenticationInfo()) {
            b.append("user", c.getAuthenticationInfo()->getUser(nsToDatabase(ns)));
        }

        BSONObj p = b.done();

        if (static_cast<size_t>(p.objsize()) > MAX_PROFILE_DOC_SIZE_BYTES || isQueryObjTooBig) {
            string small = p.toString(/*isArray*/false, /*full*/false);

            warning() << "can't add full line to system.profile: " << small << endl;

            // rebuild with limited info
            BSONObjBuilder b(profileBufBuilder);
            b.appendDate("ts", jsTime());
            b.append("client", c.clientAddress() );
            if ( c.getAuthenticationInfo() )
                b.append( "user" , c.getAuthenticationInfo()->getUser( nsToDatabase( ns ) ) );

            b.append("err", "profile line too large (max is 100KB)");

            // should be much smaller but if not don't break anything
            if (small.size() < MAX_PROFILE_DOC_SIZE_BYTES){
                b.append("abbreviated", small);
            }

            p = b.done();
        }

        // write: not replicated
        // get or create the profiling collection
        NamespaceDetails *details = getOrCreateProfileCollection(db);
        if (details) {
            int len = p.objsize();
            Record *r = theDataFileMgr.fast_oplog_insert(details, ns, len);
            memcpy(getDur().writingPtr(r->data(), len), p.objdata(), len);
        }
    }
Exemple #20
0
    void inProgCmd( Message &m, DbResponse &dbresponse ) {
        BSONObjBuilder b;

        if (!cc().getAuthorizationManager()->checkAuthorization(
                AuthorizationManager::SERVER_RESOURCE_NAME, ActionType::inprog)) {
            b.append("err", "unauthorized");
        }
        else {
            DbMessage d(m);
            QueryMessage q(d);
            bool all = q.query["$all"].trueValue();
            vector<BSONObj> vals;
            {
                Client& me = cc();
                scoped_lock bl(Client::clientsMutex);
                scoped_ptr<Matcher> m(new Matcher(q.query));
                for( set<Client*>::iterator i = Client::clients.begin(); i != Client::clients.end(); i++ ) {
                    Client *c = *i;
                    verify( c );
                    CurOp* co = c->curop();
                    if ( c == &me && !co ) {
                        continue;
                    }
                    verify( co );
                    if( all || co->displayInCurop() ) {
                        BSONObj info = co->info();
                        if ( all || m->matches( info )) {
                            vals.push_back( info );
                        }
                    }
                }
            }
            b.append("inprog", vals);
            if( lockedForWriting() ) {
                b.append("fsyncLock", true);
                b.append("info", "use db.fsyncUnlock() to terminate the fsync write/snapshot lock");
            }
        }

        replyToQuery(0, m, dbresponse, b.obj());
    }
Exemple #21
0
    void receivedUpdate(Message& m, CurOp& op) {
        DbMessage d(m);
        const char *ns = d.getns();
        assert(*ns);
        op.debug().str << ns << ' ';
        int flags = d.pullInt();
        BSONObj query = d.nextJsObj();

        assert( d.moreJSObjs() );
        assert( query.objsize() < m.header()->dataLen() );
        BSONObj toupdate = d.nextJsObj();
        uassert( 10055 , "update object too large", toupdate.objsize() <= BSONObjMaxUserSize);
        assert( toupdate.objsize() < m.header()->dataLen() );
        assert( query.objsize() + toupdate.objsize() < m.header()->dataLen() );
        bool upsert = flags & UpdateOption_Upsert;
        bool multi = flags & UpdateOption_Multi;
        bool broadcast = flags & UpdateOption_Broadcast;
        {
            string s = query.toString();
            /* todo: we shouldn't do all this ss stuff when we don't need it, it will slow us down.
               instead, let's just story the query BSON in the debug object, and it can toString()
               lazily
            */
            op.debug().str << " query: " << s;
            op.setQuery(query);
        }

        writelock lk;

        // writelock is used to synchronize stepdowns w/ writes
        uassert( 10054 ,  "not master", isMasterNs( ns ) );
        
        // if this ever moves to outside of lock, need to adjust check Client::Context::_finishInit
        if ( ! broadcast && handlePossibleShardedMessage( m , 0 ) )
            return;

        Client::Context ctx( ns );

        UpdateResult res = updateObjects(ns, toupdate, query, upsert, multi, true, op.debug() );
        lastError.getSafe()->recordUpdate( res.existing , res.num , res.upserted ); // for getlasterror
    }
Exemple #22
0
    void inProgCmd( Message &m, DbResponse &dbresponse ) {
        BSONObjBuilder b;

        if( ! cc().isAdmin() ) {
            b.append("err", "unauthorized");
        }
        else {
            DbMessage d(m);
            QueryMessage q(d);
            bool all = q.query["$all"].trueValue();
            vector<BSONObj> vals;
            {
                Client& me = cc();
                scoped_lock bl(Client::clientsMutex);
                auto_ptr<Matcher> m(new Matcher(q.query));
                for( set<Client*>::iterator i = Client::clients.begin(); i != Client::clients.end(); i++ ) {
                    Client *c = *i;
                    assert( c );
                    CurOp* co = c->curop();
                    if ( c == &me && !co ) {
                        continue;
                    }
                    assert( co );
                    if( all || co->active() ) {
                        BSONObj info = co->infoNoauth();
                        if ( all || m->matches( info )) {
                            vals.push_back( info );
                        }
                    }
                }
            }
            b.append("inprog", vals);
            unsigned x = lockedForWriting;
            if( x ) {
                b.append("fsyncLock", x);
                b.append("info", "use db.fsyncUnlock() to terminate the fsync write/snapshot lock");
            }
        }

        replyToQuery(0, m, dbresponse, b.obj());
    }
Exemple #23
0
 void ClientCursor::staticYield( int micros , const StringData& ns ) {
     killCurrentOp.checkForInterrupt( false );
     {
         dbtempreleasecond unlock;
         if ( unlock.unlocked() ) {
             if ( micros == -1 )
                 micros = Client::recommendedYieldMicros();
             if ( micros > 0 )
                 sleepmicros( micros );
         }
         else {
             CurOp * c = cc().curop();
             while ( c->parent() )
                 c = c->parent();
             warning() << "ClientCursor::yield can't unlock b/c of recursive lock"
                       << " ns: " << ns 
                       << " top: " << c->info()
                       << endl;
         }
     }
 }
    void OpDebug::append( const CurOp& curop, BSONObjBuilder& b ) const {
        b.append( "op" , iscommand ? "command" : opToString( op ) );
        b.append( "ns" , ns.toString() );
        if ( ! query.isEmpty() )
            b.append( iscommand ? "command" : "query" , query );
        else if ( ! iscommand && curop.haveQuery() )
            curop.appendQuery( b , "query" );

        if ( ! updateobj.isEmpty() )
            b.append( "updateobj" , updateobj );
        
        const bool moved = (nmoved >= 1);

        OPDEBUG_APPEND_NUMBER( cursorid );
        OPDEBUG_APPEND_NUMBER( ntoreturn );
        OPDEBUG_APPEND_NUMBER( ntoskip );
        OPDEBUG_APPEND_BOOL( exhaust );

        OPDEBUG_APPEND_NUMBER( nscanned );
        OPDEBUG_APPEND_BOOL( idhack );
        OPDEBUG_APPEND_BOOL( scanAndOrder );
        OPDEBUG_APPEND_BOOL( moved );
        OPDEBUG_APPEND_NUMBER( nmoved );
        OPDEBUG_APPEND_NUMBER( nupdated );
        OPDEBUG_APPEND_BOOL( fastmod );
        OPDEBUG_APPEND_BOOL( fastmodinsert );
        OPDEBUG_APPEND_BOOL( upsert );
        OPDEBUG_APPEND_NUMBER( keyUpdates );

        b.appendNumber( "numYield" , curop.numYields() );
        b.append( "lockStats" , curop.lockStat().report() );
        
        if ( ! exceptionInfo.empty() ) 
            exceptionInfo.append( b , "exception" , "exceptionCode" );
        
        OPDEBUG_APPEND_NUMBER( nreturned );
        OPDEBUG_APPEND_NUMBER( responseLength );
        b.append( "millis" , executionTime );
        
    }
Exemple #25
0
    static void lockedReceivedInsert(const char *ns, Message &m, const vector<BSONObj> &objs, CurOp &op, const bool keepGoing) {
        // writelock is used to synchronize stepdowns w/ writes
        uassert(10058, "not master", isMasterNs(ns));

        Client::Context ctx(ns);
        scoped_ptr<Client::AlternateTransactionStack> altStack(opNeedsAltTxn(ns) ? new Client::AlternateTransactionStack : NULL);
        Client::Transaction transaction(DB_SERIALIZABLE);
        insertObjects(ns, objs, keepGoing, 0, true);
        transaction.commit();
        size_t n = objs.size();
        globalOpCounters.gotInsert(n);
        op.debug().ninserted = n;
    }
Exemple #26
0
    void profile(const Client& c, int op, CurOp& currentOp) {
        // initialize with 1kb to start, to avoid realloc later
        // doing this outside the dblock to improve performance
        BufBuilder profileBufBuilder(1024);

        try {
            Lock::DBWrite lk( currentOp.getNS() );
            if ( dbHolder()._isLoaded( nsToDatabase( currentOp.getNS() ) , dbpath ) ) {
                Client::Context cx(currentOp.getNS(), dbpath);
                _profile(c, currentOp, profileBufBuilder);
            }
            else {
                mongo::log() << "note: not profiling because db went away - probably a close on: "
                             << currentOp.getNS() << endl;
            }
        }
        catch (const AssertionException& assertionEx) {
            warning() << "Caught Assertion while trying to profile " << opToString(op)
                      << " against " << currentOp.getNS()
                      << ": " << assertionEx.toString() << endl;
        }
    }
Exemple #27
0
    void ClientCursor::updateSlaveLocation(OperationContext* txn, CurOp& curop) {
        if (_slaveReadTill.isNull())
            return;

        verify(str::startsWith(_ns.c_str(), "local.oplog."));

        Client* c = curop.getClient();
        verify(c);
        OID rid = c->getRemoteID();
        if (!rid.isSet())
            return;

        repl::getGlobalReplicationCoordinator()->setLastOptimeForSlave(rid, _slaveReadTill);
    }
Exemple #28
0
    CurOp* CurOp::getOp(const BSONObj& criteria) {
        // Regarding Matcher: This is not quite the right hammer to use here.
        // Future: use an actual property of CurOp to flag index builds
        // and use that to filter.
        // This will probably need refactoring once we change index builds
        // to be a real command instead of an insert into system.indexes
        Matcher matcher(criteria);

        Client& me = cc();

        scoped_lock client_lock(Client::clientsMutex);
        for (std::set<Client*>::iterator it = Client::clients.begin();
             it != Client::clients.end();
             it++) {

            Client *client = *it;
            verify(client);

            CurOp* curop = client->curop();
            if (client == &me || curop == NULL) {
                continue;
            }

            if ( !curop->active() )
                continue;

            if ( curop->killPendingStrict() )
                continue;

            BSONObj info = curop->description();
            if (matcher.matches(info)) {
                return curop;
            }
        }

        return NULL;
    }
Exemple #29
0
    bool _tryQueryByPKHack(const char *ns, const BSONObj &query,
                           const ParsedQuery &pq, CurOp &curop, Message &result) {
        BSONObj resObject;

        bool found = false;
        Collection *cl = getCollection(ns);
        if (cl == NULL) {
            return false; // ns doesn't exist, fall through to optimizer for legacy reasons
        }
        const BSONObj &pk = cl->getSimplePKFromQuery(query);
        if (pk.isEmpty()) {
            return false; // unable to query by PK - resort to using the optimizer
        }
        found = queryByPKHack(cl, pk, query, resObject);

        if ( shardingState.needShardChunkManager( ns ) ) {
            ShardChunkManagerPtr m = shardingState.getShardChunkManager( ns );
            if ( m && ! m->belongsToMe( resObject ) ) {
                // I have something for this _id
                // but it doesn't belong to me
                // so return nothing
                resObject = BSONObj();
                found = false;
            }
        }

        BufBuilder bb(sizeof(QueryResult)+resObject.objsize()+32);
        bb.skip(sizeof(QueryResult));

        if ( found ) {
            fillQueryResultFromObj( bb , pq.getFields() , resObject );
        }

        auto_ptr< QueryResult > qr( (QueryResult *) bb.buf() );
        bb.decouple();
        qr->setResultFlagsToOk();
        qr->len = bb.len();

        curop.debug().responseLength = bb.len();
        qr->setOperation(opReply);
        qr->cursorId = 0;
        qr->startingFrom = 0;
        qr->nReturned = found ? 1 : 0;

        result.setData( qr.release(), true );
        return true;
    }
Exemple #30
0
    void receivedInsert(Message& m, CurOp& op) {
        DbMessage d(m);
        const char *ns = d.getns();
        op.debug().ns = ns;

        if( !d.moreJSObjs() ) {
            // strange.  should we complain?
            return;
        }
        BSONObj first = d.nextJsObj();

        vector<BSONObj> multi;
        while (d.moreJSObjs()){
            if (multi.empty()) // first pass
                multi.push_back(first);
            multi.push_back( d.nextJsObj() );
        }

        PageFaultRetryableSection s;
        while ( true ) {
            try {
                Lock::DBWrite lk(ns);
                
                // CONCURRENCY TODO: is being read locked in big log sufficient here?
                // writelock is used to synchronize stepdowns w/ writes
                uassert( 10058 , "not master", isMasterNs(ns) );
                
                if ( handlePossibleShardedMessage( m , 0 ) )
                    return;
                
                Client::Context ctx(ns);
                
                if( !multi.empty() ) {
                    const bool keepGoing = d.reservedField() & InsertOption_ContinueOnError;
                    insertMulti(keepGoing, ns, multi);
                    return;
                }
                
                checkAndInsert(ns, first);
                globalOpCounters.incInsertInWriteLock(1);
                return;
            }
            catch ( PageFaultException& e ) {
                e.touch();
            }
        }
    }