Collection* Database::createCollection(OperationContext* txn, StringData ns, const CollectionOptions& options, bool createIdIndex) { massert(17399, "collection already exists", getCollection(ns) == NULL); massertNamespaceNotIndex(ns, "createCollection"); invariant(txn->lockState()->isDbLockedForMode(name(), MODE_X)); if (serverGlobalParams.clusterRole == ClusterRole::ConfigServer && !(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); uassert(28838, "cannot create a non-capped oplog collection", options.capped || !nss.isOplog()); 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) { IndexCatalog* ic = collection->getIndexCatalog(); uassertStatusOK(ic->createIndexOnEmptyCollection(txn, ic->getDefaultIdIndexSpec())); } } 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, 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; }
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; }