Example #1
0
    bool Helpers::findById(Client& c, const char *ns, BSONObj query, BSONObj& result ,
                           bool * nsFound , bool * indexFound ) {
        d.dbMutex.assertAtLeastReadLocked();
        Database *database = c.database();
        assert( database );
        NamespaceDetails *d = database->namespaceIndex.details(ns);
        if ( ! d )
            return false;
        if ( nsFound )
            *nsFound = 1;

        int idxNo = d->findIdIndex();
        if ( idxNo < 0 )
            return false;
        if ( indexFound )
            *indexFound = 1;

        IndexDetails& i = d->idx( idxNo );

        BSONObj key = i.getKeyFromQuery( query );

        DiskLoc loc = i.idxInterface().findSingle(i , i.head , key);
        if ( loc.isNull() )
            return false;
        result = loc.obj();
        return true;
    }
Example #2
0
 IndexDescriptor* getIndex(const BSONObj& obj) {
     Client::ReadContext ctx(ns());
     Collection* collection = ctx.ctx().db()->getCollection( ns() );
     NamespaceDetails* nsd = collection->details();
     int idxNo = nsd->findIndexByKeyPattern(obj);
     return collection->getIndexCatalog()->getDescriptor( idxNo );
 }
Example #3
0
    bool compact(const string& ns, string &errmsg, bool validate, BSONObjBuilder& result, double pf, int pb) {
        massert( 14028, "bad ns", NamespaceString::normal(ns.c_str()) );
        massert( 14027, "can't compact a system namespace", !str::contains(ns, ".system.") ); // items in system.indexes cannot be moved there are pointers to those disklocs in NamespaceDetails

        bool ok;
        {
            Lock::DBWrite lk(ns);
            BackgroundOperation::assertNoBgOpInProgForNs(ns.c_str());
            Client::Context ctx(ns);
            NamespaceDetails *d = nsdetails(ns.c_str());
            massert( 13660, str::stream() << "namespace " << ns << " does not exist", d );
            massert( 13661, "cannot compact capped collection", !d->isCapped() );
            log() << "compact " << ns << " begin" << endl;
            if( pf != 0 || pb != 0 ) { 
                log() << "paddingFactor:" << pf << " paddingBytes:" << pb << endl;
            } 
            try { 
                ok = _compact(ns.c_str(), d, errmsg, validate, result, pf, pb);
            }
            catch(...) { 
                log() << "compact " << ns << " end (with error)" << endl;
                throw;
            }
            log() << "compact " << ns << " end" << endl;
        }
        return ok;
    }
    /** @param fromRepl false if from ApplyOpsCmd
        @return true if was and update should have happened and the document DNE.  see replset initial sync code.
     */
    bool applyOperation_inlock(const BSONObj& op, bool fromRepl, bool convertUpdateToUpsert) {
        LOG(6) << "applying op: " << op << endl;
        bool failedUpdate = false;

        OpCounters * opCounters = fromRepl ? &replOpCounters : &globalOpCounters;

        const char *names[] = { "o", "ns", "op", "b" };
        BSONElement fields[4];
        op.getFields(4, names, fields);

        BSONObj o;
        if( fields[0].isABSONObj() )
            o = fields[0].embeddedObject();
            
        const char *ns = fields[1].valuestrsafe();

        Lock::assertWriteLocked(ns);

        NamespaceDetails *nsd = nsdetails(ns);

        // operation type -- see logOp() comments for types
        const char *opType = fields[2].valuestrsafe();

        if ( *opType == 'i' ) {
            opCounters->gotInsert();

            const char *p = strchr(ns, '.');
            if ( p && strcmp(p, ".system.indexes") == 0 ) {
                // updates aren't allowed for indexes -- so we will do a regular insert. if index already
                // exists, that is ok.
                theDataFileMgr.insert(ns, (void*) o.objdata(), o.objsize());
            }
            else {
                // do upserts for inserts as we might get replayed more than once
                OpDebug debug;
                BSONElement _id;
                if( !o.getObjectID(_id) ) {
                    /* No _id.  This will be very slow. */
                    Timer t;
                    updateObjectsForReplication(ns, o, o, true, false, false, debug, false,
                                                QueryPlanSelectionPolicy::idElseNatural() );
                    if( t.millis() >= 2 ) {
                        RARELY OCCASIONALLY log() << "warning, repl doing slow updates (no _id field) for " << ns << endl;
                    }
                }
                else {
                    // probably don't need this since all replicated colls have _id indexes now
                    // but keep it just in case
                    RARELY if ( nsd && !nsd->isCapped() ) { ensureHaveIdIndex(ns); }

                    /* todo : it may be better to do an insert here, and then catch the dup key exception and do update
                              then.  very few upserts will not be inserts...
                              */
                    BSONObjBuilder b;
                    b.append(_id);
                    updateObjectsForReplication(ns, o, b.done(), true, false, false , debug, false,
                                                QueryPlanSelectionPolicy::idElseNatural() );
                }
            }
        }
Example #5
0
 void dupCheck(vector<IndexChanges>& v, NamespaceDetails& d, DiskLoc curObjLoc) {
     int z = d.nIndexesBeingBuilt();
     for( int i = 0; i < z; i++ ) {
         IndexDetails& idx = d.idx(i);
         v[i].dupCheck(idx, curObjLoc);
     }
 }
 void IndexCatalogEntry::setHead( DiskLoc newHead ) {
     NamespaceDetails* nsd = _collection->detailsWritable();
     int idxNo = _indexNo();
     IndexDetails& id = nsd->idx( idxNo );
     id.head.writing() = newHead;
     _head = newHead;
 }
Example #7
0
        bool touch( std::string& ns, 
                    std::string& errmsg, 
                    bool touch_data, 
                    bool touch_indexes, 
                    BSONObjBuilder& result ) {

            if (touch_data) {
                log() << "touching namespace " << ns << endl;
                touchNs( ns );
                log() << "touching namespace " << ns << " complete" << endl;
            }

            if (touch_indexes) {
                // enumerate indexes
                std::vector< std::string > indexes;
                {
                    Client::ReadContext ctx(ns);
                    NamespaceDetails *nsd = nsdetails(ns);
                    massert( 16153, "namespace does not exist", nsd );
                    
                    NamespaceDetails::IndexIterator ii = nsd->ii(); 
                    while ( ii.more() ) {
                        IndexDetails& idx = ii.next();
                        indexes.push_back( idx.indexNamespace() );
                    }
                }
                for ( std::vector<std::string>::const_iterator it = indexes.begin(); 
                      it != indexes.end(); 
                      it++ ) {
                    touchNs( *it );
                }
            }
            return true;
        }
 shared_ptr<Cursor> NamespaceDetailsTransient::getCursor( const char *ns, const BSONObj &query, const BSONObj &order ) {
     if ( query.isEmpty() && order.isEmpty() ) {
         // TODO This will not use a covered index currently.
         return theDataFileMgr.findAll( ns );
     }
     if ( isSimpleIdQuery( query ) ) {
         Database *database = cc().database();
         assert( database );
         NamespaceDetails *d = database->namespaceIndex.details(ns);
         if ( d ) {
             int idxNo = d->findIdIndex();
             if ( idxNo >= 0 ) {
                 IndexDetails& i = d->idx( idxNo );
                 BSONObj key = i.getKeyFromQuery( query );
                 return shared_ptr<Cursor>( BtreeCursor::make( d, idxNo, i, key, key, true, 1 ) );
             }
         }
     }
     auto_ptr<MultiPlanScanner> mps( new MultiPlanScanner( ns, query, order ) ); // mayYield == false
     shared_ptr<Cursor> single = mps->singleCursor();
     if ( single ) {
         if ( !query.isEmpty() && !single->matcher() ) {
             shared_ptr<CoveredIndexMatcher> matcher( new CoveredIndexMatcher( query, single->indexKeyPattern() ) );
             single->setMatcher( matcher );
         }
         return single;
     }
     return newQueryOptimizerCursor( mps );
 }
Example #9
0
    BSONObj Sync::getMissingDoc(const BSONObj& o) {
        OplogReader missingObjReader;
        const char *ns = o.getStringField("ns");

        // capped collections
        NamespaceDetails *nsd = nsdetails(ns);
        if ( nsd && nsd->isCapped() ) {
            log() << "replication missing doc, but this is okay for a capped collection (" << ns << ")" << endl;
            return BSONObj();
        }

        uassert(15916, str::stream() << "Can no longer connect to initial sync source: " << hn, missingObjReader.connect(hn));

        // might be more than just _id in the update criteria
        BSONObj query = BSONObjBuilder().append(o.getObjectField("o2")["_id"]).obj();
        BSONObj missingObj;
        try {
            missingObj = missingObjReader.findOne(ns, query);
        } catch(DBException& e) {
            log() << "replication assertion fetching missing object: " << e.what() << endl;
            throw;
        }

        return missingObj;
    }
Example #10
0
 static int handle_system_collection_insert(const char *ns, const BSONObj &obj, bool logop) {
     // Trying to insert into a system collection.  Fancy side-effects go here:
     // TODO: see insert_checkSys
     if (mongoutils::str::endsWith(ns, ".system.indexes")) {
         // obj is something like this:
         // { _id: ObjectId('511d34f6d3080c48017a14d0'), ns: "test.leif", key: { a: -1.0 }, name: "a_-1", unique: true }
         const string &coll = obj["ns"].String();
         NamespaceDetails *details = getAndMaybeCreateNS(coll.c_str(), logop);
         BSONObj key = obj["key"].Obj();
         int i = details->findIndexByKeyPattern(key);
         if (i >= 0) {
             return ASSERT_ID_DUPKEY;
         } else {
             details->createIndex(obj);
         }
     } else if (legalClientSystemNS(ns, true)) {
         if (mongoutils::str::endsWith(ns, ".system.users")) {
             uassert( 14051 , "system.users entry needs 'user' field to be a string", obj["user"].type() == String );
             uassert( 14052 , "system.users entry needs 'pwd' field to be a string", obj["pwd"].type() == String );
             uassert( 14053 , "system.users entry needs 'user' field to be non-empty", obj["user"].String().size() );
             uassert( 14054 , "system.users entry needs 'pwd' field to be non-empty", obj["pwd"].String().size() );
         }
     } else {
         uasserted(16459, str::stream() << "attempt to insert in system namespace '" << ns << "'");
     }
     return 0;
 }
Example #11
0
    /* get a table scan cursor, but can be forward or reverse direction.
       order.$natural - if set, > 0 means forward (asc), < 0 backward (desc).
    */
    shared_ptr<Cursor> findTableScan(const char *ns, const BSONObj& order, const DiskLoc &startLoc) {
        BSONElement el = order.getField("$natural"); // e.g., { $natural : -1 }

        if ( el.number() >= 0 )
            return DataFileMgr::findAll(ns, startLoc);

        // "reverse natural order"
        NamespaceDetails *d = nsdetails(ns);

        if ( !d )
            return shared_ptr<Cursor>(new BasicCursor(DiskLoc()));

        if ( !d->isCapped() ) {
            if ( !startLoc.isNull() )
                return shared_ptr<Cursor>(new ReverseCursor( startLoc ));
            Extent *e = d->lastExtent().ext();
            while ( e->lastRecord.isNull() && !e->xprev.isNull() ) {
                OCCASIONALLY out() << "  findTableScan: extent empty, skipping ahead" << endl;
                e = e->getPrevExtent();
            }
            return shared_ptr<Cursor>(new ReverseCursor( e->lastRecord ));
        }
        else {
            return shared_ptr<Cursor>( new ReverseCappedCursor( d, startLoc ) );
        }
    }
Example #12
0
    void ensureHaveIdIndex(const char* ns, bool mayInterrupt) {
        NamespaceDetails *d = nsdetails(ns);
        if ( d == 0 || d->isSystemFlagSet(NamespaceDetails::Flag_HaveIdIndex) )
            return;

        d->setSystemFlag( NamespaceDetails::Flag_HaveIdIndex );

        {
            NamespaceDetails::IndexIterator i = d->ii();
            while( i.more() ) {
                if( i.next().isIdIndex() )
                    return;
            }
        }

        string system_indexes = cc().database()->name() + ".system.indexes";

        BSONObjBuilder b;
        b.append("name", "_id_");
        b.append("ns", ns);
        b.append("key", id_obj);
        BSONObj o = b.done();

        /* edge case: note the insert could fail if we have hit maxindexes already */
        theDataFileMgr.insert(system_indexes.c_str(), o.objdata(), o.objsize(), mayInterrupt, true);
    }
Example #13
0
    void Helpers::ensureIndex(const char *ns, BSONObj keyPattern, bool unique, const char *name) {
        NamespaceDetails *d = nsdetails(ns);
        if( d == 0 )
            return;

        {
            NamespaceDetails::IndexIterator i = d->ii();
            while( i.more() ) {
                if( i.next().keyPattern().woCompare(keyPattern) == 0 )
                    return;
            }
        }

        if( d->nIndexes >= NamespaceDetails::NIndexesMax ) {
            problem() << "Helper::ensureIndex fails, MaxIndexes exceeded " << ns << '\n';
            return;
        }

        string system_indexes = cc().database()->name + ".system.indexes";

        BSONObjBuilder b;
        b.append("name", name);
        b.append("ns", ns);
        b.append("key", keyPattern);
        b.appendBool("unique", unique);
        BSONObj o = b.done();

        theDataFileMgr.insert(system_indexes.c_str(), o.objdata(), o.objsize());
    }
Example #14
0
    static void emptyOplog() {
        writelock lk(rsoplog);
        Client::Context ctx(rsoplog);
		NamespaceDetails *d = nsdetails(rsoplog);

		// temp
		if( d && d->stats.nrecords == 0 )
		  return; // already empty, ok.

        log(1) << "replSet empty oplog" << rsLog;
        d->emptyCappedCollection(rsoplog);

        /*
        string errmsg;
        bob res;
        dropCollection(rsoplog, errmsg, res);
		log() << "replSet recreated oplog so it is empty.  todo optimize this..." << rsLog;
		createOplog();*/

      	// TEMP: restart to recreate empty oplog
        //log() << "replSet FATAL error during initial sync.  mongod restart required." << rsLog;
        //dbexit( EXIT_CLEAN );

        /*
        writelock lk(rsoplog);
        Client::Context c(rsoplog, dbpath, 0, doauth/false);
        NamespaceDetails *oplogDetails = nsdetails(rsoplog);
        uassert(13412, str::stream() << "replSet error " << rsoplog << " is missing", oplogDetails != 0);
        oplogDetails->cappedTruncateAfter(rsoplog, h.commonPointOurDiskloc, false);
        */
    }
Example #15
0
        void operator()(DBClientCursorBatchIterator &i) {
            const string to_dbname = nsToDatabase(to_collection);
            while (i.moreInCurrentBatch()) {
                if (n % 128 == 127) {
                    time_t now = time(0);
                    if (now - lastLog >= 60) { 
                        // report progress
                        if (lastLog) {
                            log() << "clone " << to_collection << ' ' << n << endl;
                        }
                        lastLog = now;
                    }
                    mayInterrupt(_mayBeInterrupted);
                }

                BSONObj js = i.nextSafe();
                ++n;

                if (isindex) {
                    verify(strstr(from_collection, "system.indexes"));
                    storedForLater->push_back(fixindex(js, to_dbname).getOwned());
                }
                else {
                    try {
                        Client::ReadContext ctx(to_collection);
                        if (_isCapped) {
                            NamespaceDetails *d = nsdetails(to_collection);
                            verify(d->isCapped());
                            BSONObj pk = js["$_"].Obj();
                            BSONObjBuilder rowBuilder;                        
                            BSONObjIterator it(js);
                            while (it.moreWithEOO()) {
                                BSONElement e = it.next();
                                if (e.eoo()) {
                                    break;
                                }
                                if (!mongoutils::str::equals(e.fieldName(), "$_")) {
                                    rowBuilder.append(e);
                                }
                            }
                            BSONObj row = rowBuilder.obj();
                            d->insertObjectIntoCappedWithPK(pk, row, NamespaceDetails::NO_LOCKTREE);
                        }
                        else {
                            insertObject(to_collection, js, 0, logForRepl);
                        }
                    }
                    catch (UserException& e) {
                        error() << "error: exception cloning object in " << from_collection << ' ' << e.what() << " obj:" << js.toString() << '\n';
                        throw;
                    }

                    RARELY if ( time( 0 ) - saveLast > 60 ) {
                        log() << n << " objects cloned so far from collection " << from_collection << endl;
                        saveLast = time( 0 );
                    }
                }
            }
        }
Example #16
0
    long long Helpers::removeRange( const string& ns , const BSONObj& min , const BSONObj& max , bool yield , bool maxInclusive , RemoveCallback * callback, bool fromMigrate ) {
        BSONObj keya , keyb;
        BSONObj minClean = toKeyFormat( min , keya );
        BSONObj maxClean = toKeyFormat( max , keyb );
        verify( keya == keyb );

        Client::Context ctx(ns);

        shared_ptr<Cursor> c;
        auto_ptr<ClientCursor> cc;
        {
            NamespaceDetails* nsd = nsdetails( ns.c_str() );
            if ( ! nsd )
                return 0;
            
            int ii = nsd->findIndexByKeyPattern( keya );
            verify( ii >= 0 );
            
            IndexDetails& i = nsd->idx( ii );
            
            c.reset( BtreeCursor::make( nsd , ii , i , minClean , maxClean , maxInclusive, 1 ) );
            cc.reset( new ClientCursor( QueryOption_NoCursorTimeout , c , ns ) );
            cc->setDoingDeletes( true );
        }

        long long num = 0;

        while ( cc->ok() ) {

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

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

            DiskLoc rloc = cc->currLoc();

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

            cc->advance();
            c->prepareToTouchEarlierIterate();

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

            c->recoverFromTouchingEarlierIterate();

            getDur().commitIfNeeded();


        }

        return num;
    }
Example #17
0
NamespaceDetails* NamespaceIndex::details(const Namespace& ns) {
    if ( !_ht )
        return 0;
    NamespaceDetails *d = _ht->get(ns);
    if ( d && d->isCapped() )
        d->cappedCheckMigrate();
    return d;
}
Example #18
0
    BSONObj Sync::getMissingDoc(const BSONObj& o) {
        OplogReader missingObjReader; // why are we using OplogReader to run a non-oplog query?
        const char *ns = o.getStringField("ns");

        // capped collections
        NamespaceDetails *nsd = nsdetails(ns);
        if ( nsd && nsd->isCapped() ) {
            log() << "replication missing doc, but this is okay for a capped collection (" << ns << ")" << endl;
            return BSONObj();
        }

        const int retryMax = 3;
        for (int retryCount = 1; retryCount <= retryMax; ++retryCount) {
            if (retryCount != 1) {
                // if we are retrying, sleep a bit to let the network possibly recover
                sleepsecs(retryCount * retryCount);
            }
            try {
                bool ok = missingObjReader.connect(hn);
                if (!ok) {
                    warning() << "network problem detected while connecting to the "
                              << "sync source, attempt " << retryCount << " of "
                              << retryMax << endl;
                        continue;  // try again
                }
            } 
            catch (const SocketException&) {
                warning() << "network problem detected while connecting to the "
                          << "sync source, attempt " << retryCount << " of "
                          << retryMax << endl;
                continue; // try again
            }

            // might be more than just _id in the update criteria
            BSONObj query = BSONObjBuilder().append(o.getObjectField("o2")["_id"]).obj();
            BSONObj missingObj;
            try {
                missingObj = missingObjReader.findOne(ns, query);
            } 
            catch (const SocketException&) {
                warning() << "network problem detected while fetching a missing document from the "
                          << "sync source, attempt " << retryCount << " of "
                          << retryMax << endl;
                continue; // try again
            } 
            catch (DBException& e) {
                log() << "replication assertion fetching missing object: " << e.what() << endl;
                throw;
            }

            // success!
            return missingObj;
        }
        // retry count exceeded
        msgasserted(15916, 
                    str::stream() << "Can no longer connect to initial sync source: " << hn);
    }
Example #19
0
    static void runCappedDeleteFromOplogWithLock(const char* ns, BSONObj op) {
        NamespaceDetails* nsd = nsdetails(ns);
        BSONObj row = op[KEY_STR_ROW].Obj();
        BSONObj pk = op[KEY_STR_PK].Obj();

        uint64_t flags = NamespaceDetails::NO_LOCKTREE;
        nsd->deleteObjectFromCappedWithPK(pk, row, flags);
        nsd->notifyOfWriteOp();
    }
Example #20
0
 // static
 void IndexLegacy::postBuildHook(Collection* collection, const BSONObj& keyPattern) {
     // If it's an FTS index, we want to set the power of 2 flag.
     string pluginName = collection->getIndexCatalog()->getAccessMethodName(keyPattern);
     if (IndexNames::TEXT == pluginName) {
         NamespaceDetails* nsd = collection->details();
         if (nsd->setUserFlag(NamespaceDetails::Flag_UsePowerOf2Sizes)) {
             nsd->syncUserFlags(collection->ns().ns());
         }
     }
 }
Example #21
0
    // prefetch for an oplog operation
    void prefetchPagesForReplicatedOp(const BSONObj& op) {
        const char *opField;
        const char *opType = op.getStringField("op");
        switch (*opType) {
        case 'i': // insert
        case 'd': // delete
            opField = "o";
            break;
        case 'u': // update
            opField = "o2";
            break;
        default:
            // prefetch ignores other ops
            return;
        }
         
        BSONObj obj = op.getObjectField(opField);
        const char *ns = op.getStringField("ns");
        NamespaceDetails *nsd = nsdetails(ns);
        if (!nsd) return; // maybe not opened yet
        
        LOG(4) << "index prefetch for op " << *opType << endl;

        DEV Lock::assertAtLeastReadLocked(ns);

        // should we prefetch index pages on updates? if the update is in-place and doesn't change 
        // indexed values, it is actually slower - a lot slower if there are a dozen indexes or 
        // lots of multikeys.  possible variations (not all mutually exclusive):
        //  1) current behavior: full prefetch
        //  2) don't do it for updates
        //  3) don't do multikey indexes for updates
        //  4) don't prefetchIndexPages on some heuristic; e.g., if it's an $inc.
        //  5) if not prefetching index pages (#2), we should do it if we are upsertings and it 
        //     will be an insert. to do that we could do the prefetchRecordPage first and if DNE
        //     then we do #1.
        // 
        // note that on deletes 'obj' does not have all the keys we would want to prefetch on.
        // a way to achieve that would be to prefetch the record first, and then afterwards do 
        // this part.
        //
        prefetchIndexPages(nsd, obj);

        // do not prefetch the data for inserts; it doesn't exist yet
        // 
        // we should consider doing the record prefetch for the delete op case as we hit the record
        // when we delete.  note if done we only want to touch the first page.
        // 
        // update: do record prefetch. 
        if ((*opType == 'u') &&
            // do not prefetch the data for capped collections because
            // they typically do not have an _id index for findById() to use.
            !nsd->isCapped()) {
            prefetchRecordPages(ns, obj);
        }
    }
Example #22
0
    static void emptyOplog() {
        Client::WriteContext ctx(rsoplog);
        NamespaceDetails *d = nsdetails(rsoplog);

        // temp
        if( d && d->stats.nrecords == 0 )
            return; // already empty, ok.

        LOG(1) << "replSet empty oplog" << rsLog;
        d->emptyCappedCollection(rsoplog);
    }
Example #23
0
        bool run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
            string ns = dbname + "." + cmdObj.firstElement().valuestr();
            NamespaceDetails *d = nsdetails(ns);

            if (NULL == d) {
                errmsg = "can't find ns";
                return false;
            }

            GeoNearArguments commonArgs(cmdObj);
            if (commonArgs.numWanted < 0) {
                errmsg = "numWanted must be >= 0";
                return false;
            }

            vector<int> idxs;

            d->findIndexByType(IndexNames::GEO_2D, idxs);
            if (idxs.size() > 1) {
                errmsg = "more than one 2d index, not sure which to run geoNear on";
                return false;
            }

            unordered_map<string, double> statsMap;

            if (1 == idxs.size()) {
                result.append("ns", ns);
                twod_internal::TwoDGeoNearRunner::run2DGeoNear(d, idxs[0], cmdObj, commonArgs,
                                                               errmsg, result, &statsMap);
                BSONObjBuilder stats(result.subobjStart("stats"));
                for (unordered_map<string, double>::const_iterator it = statsMap.begin();
                     it != statsMap.end(); ++it) {
                    stats.append(it->first, it->second);
                }
                stats.append("time", cc().curop()->elapsedMillis());
                stats.done();
                return true;
            }

            d->findIndexByType(IndexNames::GEO_2DSPHERE, idxs);
            if (idxs.size() > 1) {
                errmsg = "more than one 2dsphere index, not sure which to run geoNear on";
                return false;
            }

            if (1 == idxs.size()) {
                result.append("ns", ns);
                run2DSphereGeoNear(d, idxs[0], cmdObj, commonArgs, errmsg, result);
                return true;
            }

            errmsg = "no geo indices for geoNear";
            return false;
        }
        void run() {
            // This will succeed, but not insert anything because they are changed to upserts
            for (int i=0; i<150; i++) {
                insertSucceed();
            }

            // Just to be sure, no _id index, right?
            Client::Context ctx(cappedNs());
            NamespaceDetails *nsd = nsdetails(cappedNs().c_str());
            verify(nsd->findIdIndex() == -1);
        }
Example #25
0
    Status Database::renameCollection( const StringData& fromNS, const StringData& toNS,
                                       bool stayTemp ) {

        // move data namespace
        Status s = _renameSingleNamespace( fromNS, toNS, stayTemp );
        if ( !s.isOK() )
            return s;

        NamespaceDetails* details = _namespaceIndex.details( toNS );
        verify( details );

        // move index namespaces
        string indexName = _name + ".system.indexes";
        BSONObj oldIndexSpec;
        while( Helpers::findOne( indexName, BSON( "ns" << fromNS ), oldIndexSpec ) ) {
            oldIndexSpec = oldIndexSpec.getOwned();

            BSONObj newIndexSpec;
            {
                BSONObjBuilder b;
                BSONObjIterator i( oldIndexSpec );
                while( i.more() ) {
                    BSONElement e = i.next();
                    if ( strcmp( e.fieldName(), "ns" ) != 0 )
                        b.append( e );
                    else
                        b << "ns" << toNS;
                }
                newIndexSpec = b.obj();
            }

            DiskLoc newIndexSpecLoc = theDataFileMgr.insert( indexName.c_str(),
                                                             newIndexSpec.objdata(),
                                                             newIndexSpec.objsize(),
                                                             false,
                                                             true,
                                                             false );
            int indexI = details->findIndexByName( oldIndexSpec.getStringField( "name" ) );
            IndexDetails &indexDetails = details->idx(indexI);
            string oldIndexNs = indexDetails.indexNamespace();
            indexDetails.info = newIndexSpecLoc;
            string newIndexNs = indexDetails.indexNamespace();

            Status s = _renameSingleNamespace( oldIndexNs, newIndexNs, false );
            if ( !s.isOK() )
                return s;

            deleteObjects( indexName.c_str(), oldIndexSpec, true, false, true );
        }

        Top::global.collectionDropped( fromNS.toString() );

        return Status::OK();
    }
Example #26
0
        virtual bool run(const string& db, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
            string coll = cmdObj.firstElement().valuestr();
            if( coll.empty() || db.empty() ) {
                errmsg = "no collection name specified";
                return false;
            }

            if( isCurrentlyAReplSetPrimary() && !cmdObj["force"].trueValue() ) { 
                errmsg = "will not run compact on an active replica set primary as this is a slow blocking operation. use force:true to force";
                return false;
            }
            
            string ns = db + '.' + coll;
            if ( ! NamespaceString::normal(ns.c_str()) ) {
                errmsg = "bad namespace name";
                return false;
            }
            
            // parameter validation to avoid triggering assertions in compact()
            if ( str::contains(ns, ".system.") ) {
                errmsg = "can't compact a system namespace";
                return false;
            }
            
            {
                Lock::DBWrite lk(ns);
                Client::Context ctx(ns);
                NamespaceDetails *d = nsdetails(ns.c_str());
                if( ! d ) {
                    errmsg = "namespace does not exist";
                    return false;
                }

                if ( d->isCapped() ) {
                    errmsg = "cannot compact a capped collection";
                    return false;
                }
            }

            double pf = 1.0;
            int pb = 0;
            if( cmdObj.hasElement("paddingFactor") ) {
                pf = cmdObj["paddingFactor"].Number();
                verify( pf >= 1.0 && pf <= 4.0 );
            }
            if( cmdObj.hasElement("paddingBytes") ) {
                pb = (int) cmdObj["paddingBytes"].Number();
                verify( pb >= 0 && pb <= 1024 * 1024 );
            }

            bool validate = !cmdObj.hasElement("validate") || cmdObj["validate"].trueValue(); // default is true at the moment
            bool ok = compact(ns, errmsg, validate, result, pf, pb);
            return ok;
        }
Example #27
0
 static void runCappedInsertFromOplogWithLock(
     const char* ns, 
     BSONObj& pk,
     BSONObj& row
     ) 
 {
     NamespaceDetails *nsd = nsdetails(ns);
     // overwrite set to true because we are running on a secondary
     const uint64_t flags = (NamespaceDetails::NO_UNIQUE_CHECKS | NamespaceDetails::NO_LOCKTREE);        
     nsd->insertObjectIntoCappedWithPK(pk, row, flags);
     nsd->notifyOfWriteOp();
 }
Example #28
0
 bool RestAdminAccess::haveAdminUsers() const {
     Client::Transaction txn(DB_TXN_READ_ONLY | DB_TXN_SNAPSHOT);
     openAdminDb();
     readlocktry rl(/*"admin.system.users", */10000);
     uassert( 16173 , "couldn't get read lock to get admin auth credentials" , rl.got() );
     Client::Context cx( "admin.system.users", dbpath, false );
     BSONObj o;
     NamespaceDetails *d = nsdetails( "admin.system.users" );
     bool ok = d != NULL && d->findOne(BSONObj(), o);
     txn.commit();
     return ok;
 }
Example #29
0
 void IndexCatalogEntry::setMultikey() {
     if ( isMultikey() )
         return;
     NamespaceDetails* nsd = _collection->detailsWritable();
     int idxNo = _indexNo();
     if ( nsd->setIndexIsMultikey( idxNo, true ) ) {
         LOG(1) << _collection->ns().ns() << ": clearing plan cache - index "
                << _descriptor->keyPattern() << " set to multi key.";
         _collection->infoCache()->clearQueryCache();
     }
     _isMultikey = true;
 }
        void run() {
            // This will succeed, but not insert anything because they are changed to upserts
            for (int i=0; i<150; i++) {
                insertSucceed();
            }

            // this changed in 2.1.2
            // we now have indexes on capped collections
            Client::Context ctx(cappedNs());
            NamespaceDetails *nsd = nsdetails(cappedNs().c_str());
            verify(nsd->findIdIndex() >= 0);
        }