RecordId Helpers::findOne(OperationContext* opCtx, Collection* collection, std::unique_ptr<QueryRequest> qr, bool requireIndex) { if (!collection) return RecordId(); const ExtensionsCallbackReal extensionsCallback(opCtx, &collection->ns()); const boost::intrusive_ptr<ExpressionContext> expCtx; auto statusWithCQ = CanonicalQuery::canonicalize(opCtx, std::move(qr), expCtx, extensionsCallback, MatchExpressionParser::kAllowAllSpecialFeatures); massertStatusOK(statusWithCQ.getStatus()); unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue()); size_t options = requireIndex ? QueryPlannerParams::NO_TABLE_SCAN : QueryPlannerParams::DEFAULT; auto exec = uassertStatusOK( getExecutor(opCtx, collection, std::move(cq), PlanExecutor::NO_YIELD, options)); PlanExecutor::ExecState state; BSONObj obj; RecordId loc; if (PlanExecutor::ADVANCED == (state = exec->getNext(&obj, &loc))) { return loc; } massert(34427, "Plan executor error: " + WorkingSetCommon::toStatusString(obj), PlanExecutor::IS_EOF == state); return RecordId(); }
Collection* Database::createCollection( OperationContext* txn, const StringData& ns, const CollectionOptions& options, bool allocateDefaultSpace, bool createIdIndex ) { massert( 17399, "collection already exists", getCollection( txn, ns ) == NULL ); massertNamespaceNotIndex( ns, "createCollection" ); if ( serverGlobalParams.configsvr && !( ns.startsWith( "config." ) || ns.startsWith( "local." ) || ns.startsWith( "admin." ) ) ) { uasserted(14037, "can't create user databases on a --configsvr instance"); } if (NamespaceString::normal(ns)) { // This check only applies for actual collections, not indexes or other types of ns. uassert(17381, str::stream() << "fully qualified namespace " << ns << " is too long " << "(max is " << NamespaceString::MaxNsCollectionLen << " bytes)", ns.size() <= NamespaceString::MaxNsCollectionLen); } NamespaceString nss( ns ); uassert( 17316, "cannot create a blank collection", nss.coll() > 0 ); audit::logCreateCollection( currentClient.get(), ns ); txn->recoveryUnit()->registerChange( new AddCollectionChange(this, ns) ); Status status = _dbEntry->createCollection(txn, ns, options, allocateDefaultSpace); massertStatusOK(status); Collection* collection = getCollection(txn, ns); invariant(collection); if ( createIdIndex ) { if ( collection->requiresIdIndex() ) { if ( options.autoIndexId == CollectionOptions::YES || options.autoIndexId == CollectionOptions::DEFAULT ) { IndexCatalog* ic = collection->getIndexCatalog(); uassertStatusOK( ic->createIndexOnEmptyCollection(txn, ic->getDefaultIdIndexSpec())); } } if ( nss.isSystem() ) { authindex::createSystemIndexes( txn, collection ); } } return collection; }
RecordStoreV1Base* MMAPV1DatabaseCatalogEntry::_getIndexRecordStore( OperationContext* txn ) { NamespaceString nss( name(), "system.indexes" ); RecordStoreV1Base* rs = _getRecordStore( txn, nss.ns() ); if ( rs != NULL ) return rs; CollectionOptions options; Status status = createCollection( txn, nss.ns(), options, true ); massertStatusOK( status ); rs = _getRecordStore( txn, nss.ns() ); invariant( rs ); return rs; }
RecordStoreV1Base* MMAP1DatabaseCatalogEntry::_getNamespaceRecordStore( OperationContext* txn, const StringData& whosAsking) { NamespaceString nss( _name, "system.namespaces" ); if ( nss == whosAsking ) return NULL; RecordStoreV1Base* rs = _getRecordStore( txn, nss.ns() ); if ( rs != NULL ) return rs; CollectionOptions options; Status status = createCollection( txn, nss.ns(), options, true ); massertStatusOK( status ); rs = _getRecordStore( txn, nss.ns() ); invariant( rs ); return rs; }
void MMAPV1DatabaseCatalogEntry::_addNamespaceToNamespaceCollection( OperationContext* txn, const StringData& ns, const BSONObj* options ) { if ( nsToCollectionSubstring( ns ) == "system.namespaces" ) { // system.namespaces holds all the others, so it is not explicitly listed in the catalog. return; } BSONObjBuilder b; b.append("name", ns); if ( options && !options->isEmpty() ) b.append("options", *options); BSONObj obj = b.done(); RecordStoreV1Base* rs = _getNamespaceRecordStore( txn, ns ); invariant( rs ); StatusWith<DiskLoc> loc = rs->insertRecord( txn, obj.objdata(), obj.objsize(), -1 ); massertStatusOK( loc.getStatus() ); }