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; }
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 ); }
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() ); } } }
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; }
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 ); }
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; }
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; }
/* 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 ) ); } }
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); }
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()); }
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); */ }
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 ); } } } }
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; }
NamespaceDetails* NamespaceIndex::details(const Namespace& ns) { if ( !_ht ) return 0; NamespaceDetails *d = _ht->get(ns); if ( d && d->isCapped() ) d->cappedCheckMigrate(); return d; }
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); }
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(); }
// 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()); } } }
// 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); } }
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); }
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); }
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(); }
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; }
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(); }
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; }
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); }