Collection* Database::createCollection(OperationContext* txn, StringData ns, const CollectionOptions& options, bool createIdIndex) { invariant(txn->lockState()->isDbLockedForMode(name(), MODE_X)); invariant(!options.isView()); NamespaceString nss(ns); _checkCanCreateCollection(nss, options); audit::logCreateCollection(&cc(), ns); txn->recoveryUnit()->registerChange(new AddCollectionChange(txn, this, ns)); Status status = _dbEntry->createCollection(txn, ns, options, true /*allocateDefaultSpace*/); massertNoTraceStatusOK(status); Collection* collection = _getOrCreateCollectionInstance(txn, ns); invariant(collection); _collections[ns] = collection; if (createIdIndex) { if (collection->requiresIdIndex()) { if (options.autoIndexId == CollectionOptions::YES || options.autoIndexId == CollectionOptions::DEFAULT) { // The creation of the _id index isn't replicated and is instead implicit in the // creation of the collection. This means that the version of the _id index to build // is technically unspecified. However, we're able to use the // featureCompatibilityVersion of this server to determine the default index version // to use because we apply commands (opType == 'c') in their own batch. This // guarantees the write to the admin.system.version collection from the // "setFeatureCompatibilityVersion" command either happens entirely before the // collection creation or it happens entirely after. const auto featureCompatibilityVersion = serverGlobalParams.featureCompatibilityVersion.load(); IndexCatalog* ic = collection->getIndexCatalog(); uassertStatusOK(ic->createIndexOnEmptyCollection( txn, ic->getDefaultIdIndexSpec(featureCompatibilityVersion))); } } if (nss.isSystem()) { authindex::createSystemIndexes(txn, collection); } } auto opObserver = getGlobalServiceContext()->getOpObserver(); if (opObserver) opObserver->onCreateCollection(txn, nss, options); return collection; }
Collection* Database::createCollection(OperationContext* txn, StringData ns, const CollectionOptions& options, bool createIdIndex, const BSONObj& idIndex) { invariant(txn->lockState()->isDbLockedForMode(name(), MODE_X)); invariant(!options.isView()); NamespaceString nss(ns); _checkCanCreateCollection(nss, options); audit::logCreateCollection(&cc(), ns); Status status = _dbEntry->createCollection(txn, ns, options, true /*allocateDefaultSpace*/); massertNoTraceStatusOK(status); txn->recoveryUnit()->registerChange(new AddCollectionChange(txn, this, ns)); Collection* collection = _getOrCreateCollectionInstance(txn, ns); invariant(collection); _collections[ns] = collection; BSONObj fullIdIndexSpec; if (createIdIndex) { if (collection->requiresIdIndex()) { if (options.autoIndexId == CollectionOptions::YES || options.autoIndexId == CollectionOptions::DEFAULT) { const auto featureCompatibilityVersion = serverGlobalParams.featureCompatibility.version.load(); IndexCatalog* ic = collection->getIndexCatalog(); fullIdIndexSpec = uassertStatusOK(ic->createIndexOnEmptyCollection( txn, !idIndex.isEmpty() ? idIndex : ic->getDefaultIdIndexSpec(featureCompatibilityVersion))); } } if (nss.isSystem()) { authindex::createSystemIndexes(txn, collection); } } auto opObserver = getGlobalServiceContext()->getOpObserver(); if (opObserver) opObserver->onCreateCollection(txn, nss, options, fullIdIndexSpec); return collection; }
Status Database::createView(OperationContext* txn, StringData ns, const CollectionOptions& options) { invariant(txn->lockState()->isDbLockedForMode(name(), MODE_X)); invariant(options.isView()); NamespaceString nss(ns); NamespaceString viewOnNss(nss.db(), options.viewOn); _checkCanCreateCollection(nss, options); audit::logCreateCollection(&cc(), ns); if (nss.isOplog()) return Status(ErrorCodes::InvalidNamespace, str::stream() << "invalid namespace name for a view: " + nss.toString()); return _views.createView(txn, nss, viewOnNss, BSONArray(options.pipeline), options.collation); }