bool _userCreateNS(const char *ns, const BSONObj& options, string& err, bool *deferIdIndex) { LOG(1) << "create collection " << ns << ' ' << options << endl; if ( nsdetails(ns) ) { err = "collection already exists"; return false; } long long size = Extent::initialSize(128); { BSONElement e = options.getField("size"); if ( e.isNumber() ) { size = e.numberLong(); uassert( 10083 , "create collection invalid size spec", size >= 0 ); size += 0xff; size &= 0xffffffffffffff00LL; if ( size < Extent::minSize() ) size = Extent::minSize(); } } bool newCapped = false; long long mx = 0; if( options["capped"].trueValue() ) { newCapped = true; BSONElement e = options.getField("max"); if ( e.isNumber() ) { mx = e.numberLong(); uassert( 16495, "max in a capped collection has to be < 2^31 or not set", NamespaceDetails::validMaxCappedDocs(&mx) ); } } cc().database()->createCollection( ns, options["capped"].trueValue(), &options ); Collection* collection = cc().database()->getCollection( ns ); verify( collection ); // $nExtents just for debug/testing. BSONElement e = options.getField( "$nExtents" ); if ( e.type() == Array ) { // We create one extent per array entry, with size specified // by the array value. BSONObjIterator i( e.embeddedObject() ); while( i.more() ) { BSONElement e = i.next(); int size = int( e.number() ); verify( size <= 0x7fffffff ); // $nExtents is just for testing - always allocate new extents // rather than reuse existing extents so we have some predictibility // in the extent size used by our tests collection->increaseStorageSize( (int)size, false ); } } else if ( int( e.number() ) > 0 ) { // We create '$nExtents' extents, each of size 'size'. int nExtents = int( e.number() ); verify( size <= 0x7fffffff ); for ( int i = 0; i < nExtents; ++i ) { verify( size <= 0x7fffffff ); // $nExtents is just for testing - always allocate new extents // rather than reuse existing extents so we have some predictibility // in the extent size used by our tests collection->increaseStorageSize( (int)size, false ); } } else { // This is the non test case, where we don't have a $nExtents spec. while ( size > 0 ) { const int max = Extent::maxSize(); const int min = Extent::minSize(); int desiredExtentSize = static_cast<int> (size > max ? max : size); desiredExtentSize = static_cast<int> (desiredExtentSize < min ? min : desiredExtentSize); desiredExtentSize &= 0xffffff00; Extent* e = collection->increaseStorageSize( (int)desiredExtentSize, true ); size -= e->length; } } NamespaceDetails *d = nsdetails(ns); verify(d); bool ensure = true; // respect autoIndexId if set. otherwise, create an _id index for all colls, except for // capped ones in local w/o autoIndexID (reason for the exception is for the oplog and // non-replicated capped colls) if( options.hasField( "autoIndexId" ) || (newCapped && nsToDatabase( ns ) == "local" ) ) { ensure = options.getField( "autoIndexId" ).trueValue(); } if( ensure ) { if( deferIdIndex ) *deferIdIndex = true; else ensureIdIndexForNewNs( ns ); } if ( mx > 0 ) d->setMaxCappedDocs( mx ); if ( options["flags"].numberInt() ) { d->replaceUserFlags( options["flags"].numberInt() ); } return true; }