StatusWith<DiskLoc> Collection::_insertDocument( const BSONObj& docToInsert, bool enforceQuota ) { // TODO: for now, capped logic lives inside NamespaceDetails, which is hidden // under the RecordStore, this feels broken since that should be a // collection access method probably StatusWith<DiskLoc> loc = _recordStore->insertRecord( docToInsert.objdata(), docToInsert.objsize(), enforceQuota ? largestFileNumberInQuota() : 0 ); if ( !loc.isOK() ) return loc; _infoCache.notifyOfWriteOp(); try { _indexCatalog.indexRecord( docToInsert, loc.getValue() ); } catch ( AssertionException& e ) { if ( _details->isCapped() ) { return StatusWith<DiskLoc>( ErrorCodes::InternalError, str::stream() << "unexpected index insertion failure on" << " capped collection" << e.toString() << " - collection and its index will not match" ); } // indexRecord takes care of rolling back indexes // so we just have to delete the main storage _recordStore->deleteRecord( loc.getValue() ); return StatusWith<DiskLoc>( e.toStatus( "insertDocument" ) ); } return loc; }
StatusWith<DiskLoc> Collection::insertDocument( const DocWriter* doc, bool enforceQuota ) { verify( _indexCatalog.numIndexesTotal() == 0 ); // eventually can implement, just not done StatusWith<DiskLoc> loc = _recordStore->insertRecord( doc, enforceQuota ? largestFileNumberInQuota() : 0 ); if ( !loc.isOK() ) return loc; return StatusWith<DiskLoc>( loc ); }
StatusWith<DiskLoc> Collection::insertDocument( const BSONObj& docToInsert, bool enforceQuota ) { int lenWHdr = _details->getRecordAllocationSize( docToInsert.objsize() + Record::HeaderSize ); fassert( 17208, lenWHdr >= ( docToInsert.objsize() + Record::HeaderSize ) ); if ( _details->isCapped() ) { // TOOD: old god not done Status ret = _indexCatalog.checkNoIndexConflicts( docToInsert ); uassert(17209, "duplicate key insert for unique index of capped collection", ret.isOK() ); } // TODO: for now, capped logic lives inside NamespaceDetails, which is hidden // under the RecordStore, this feels broken since that should be a // collection access method probably StatusWith<DiskLoc> loc = _recordStore.allocRecord( lenWHdr, enforceQuota ? largestFileNumberInQuota() : 0 ); if ( !loc.isOK() ) return loc; Record *r = loc.getValue().rec(); fassert( 17210, r->lengthWithHeaders() >= lenWHdr ); // copy the data r = reinterpret_cast<Record*>( getDur().writingPtr(r, lenWHdr) ); memcpy( r->data(), docToInsert.objdata(), docToInsert.objsize() ); addRecordToRecListInExtent(r, loc.getValue()); // XXX move down into record store _details->incrementStats( r->netLength(), 1 ); // TOOD: old god not done _infoCache.notifyOfWriteOp(); try { _indexCatalog.indexRecord( docToInsert, loc.getValue() ); } catch( AssertionException& e ) { if ( _details->isCapped() ) { return StatusWith<DiskLoc>( ErrorCodes::InternalError, str::stream() << "unexpected index insertion failure on" << " capped collection" << e.toString() << " - collection and its index will not match" ); } // normal case -- we can roll back deleteDocument( loc.getValue(), false, true, NULL ); throw; } // TODO: this is what the old code did, but is it correct? _details->paddingFits(); return loc; }
StatusWith<DiskLoc> Collection::updateDocument( OperationContext* txn, const DiskLoc& oldLocation, const BSONObj& objNew, bool enforceQuota, OpDebug* debug ) { Record* oldRecord = _recordStore->recordFor( oldLocation ); BSONObj objOld( oldRecord->data() ); if ( objOld.hasElement( "_id" ) ) { BSONElement oldId = objOld["_id"]; BSONElement newId = objNew["_id"]; if ( oldId != newId ) return StatusWith<DiskLoc>( ErrorCodes::InternalError, "in Collection::updateDocument _id mismatch", 13596 ); } if ( ns().coll() == "system.users" ) { // XXX - andy and spencer think this should go away now V2UserDocumentParser parser; Status s = parser.checkValidUserDocument(objNew); if ( !s.isOK() ) return StatusWith<DiskLoc>( s ); } /* duplicate key check. we descend the btree twice - once for this check, and once for the actual inserts, further below. that is suboptimal, but it's pretty complicated to do it the other way without rollbacks... */ OwnedPointerMap<IndexDescriptor*,UpdateTicket> updateTickets; IndexCatalog::IndexIterator ii = _indexCatalog.getIndexIterator( true ); while ( ii.more() ) { IndexDescriptor* descriptor = ii.next(); IndexAccessMethod* iam = _indexCatalog.getIndex( descriptor ); InsertDeleteOptions options; options.logIfError = false; options.dupsAllowed = !(KeyPattern::isIdKeyPattern(descriptor->keyPattern()) || descriptor->unique()) || replset::ignoreUniqueIndex(descriptor); UpdateTicket* updateTicket = new UpdateTicket(); updateTickets.mutableMap()[descriptor] = updateTicket; Status ret = iam->validateUpdate(objOld, objNew, oldLocation, options, updateTicket ); if ( !ret.isOK() ) { return StatusWith<DiskLoc>( ret ); } } // this can callback into Collection::recordStoreGoingToMove StatusWith<DiskLoc> newLocation = _recordStore->updateRecord( txn, oldLocation, objNew.objdata(), objNew.objsize(), enforceQuota ? largestFileNumberInQuota() : 0, this ); if ( !newLocation.isOK() ) { return newLocation; } _infoCache.notifyOfWriteOp(); if ( newLocation.getValue() != oldLocation ) { if ( debug ) { if (debug->nmoved == -1) // default of -1 rather than 0 debug->nmoved = 1; else debug->nmoved += 1; } _indexCatalog.indexRecord(txn, objNew, newLocation.getValue()); return newLocation; } if ( debug ) debug->keyUpdates = 0; ii = _indexCatalog.getIndexIterator( true ); while ( ii.more() ) { IndexDescriptor* descriptor = ii.next(); IndexAccessMethod* iam = _indexCatalog.getIndex( descriptor ); int64_t updatedKeys; Status ret = iam->update(txn, *updateTickets.mutableMap()[descriptor], &updatedKeys); if ( !ret.isOK() ) return StatusWith<DiskLoc>( ret ); if ( debug ) debug->keyUpdates += updatedKeys; } // Broadcast the mutation so that query results stay correct. _cursorCache.invalidateDocument(oldLocation, INVALIDATION_MUTATION); return newLocation; }
Extent* Collection::increaseStorageSize( int size, bool enforceQuota ) { return getExtentManager()->increaseStorageSize( _ns, _details, size, enforceQuota ? largestFileNumberInQuota() : 0 ); }
void Collection::increaseStorageSize( int size, bool enforceQuota ) { _recordStore->increaseStorageSize( size, enforceQuota ? largestFileNumberInQuota() : 0 ); }