BatchedCommandRequest* msgToBatchUpdate( const Message& updateMsg ) { // Parsing DbMessage throws DbMessage dbMsg( updateMsg ); NamespaceString nss( dbMsg.getns() ); int flags = dbMsg.pullInt(); bool upsert = flags & UpdateOption_Upsert; bool multi = flags & UpdateOption_Multi; const BSONObj query = dbMsg.nextJsObj(); const BSONObj updateExpr = dbMsg.nextJsObj(); // No exceptions from here on BatchedUpdateDocument* updateDoc = new BatchedUpdateDocument; updateDoc->setQuery( query ); updateDoc->setUpdateExpr( updateExpr ); updateDoc->setUpsert( upsert ); updateDoc->setMulti( multi ); BatchedCommandRequest* request = new BatchedCommandRequest( BatchedCommandRequest::BatchType_Update ); request->setNS( nss.ns() ); request->getUpdateRequest()->addToUpdates( updateDoc ); return request; }
BatchedCommandRequest* msgToBatchInsert( const Message& insertMsg ) { // Parsing DbMessage throws DbMessage dbMsg( insertMsg ); NamespaceString nss( dbMsg.getns() ); bool coe = dbMsg.reservedField() & Reserved_InsertOption_ContinueOnError; vector<BSONObj> docs; do { docs.push_back( dbMsg.nextJsObj() ); } while ( dbMsg.moreJSObjs() ); // Continue-on-error == unordered bool ordered = !coe; // No exceptions from here on BatchedCommandRequest* request = new BatchedCommandRequest( BatchedCommandRequest::BatchType_Insert ); request->setNS( nss.ns() ); for ( vector<BSONObj>::const_iterator it = docs.begin(); it != docs.end(); ++it ) { request->getInsertRequest()->addToDocuments( *it ); } request->setOrdered( ordered ); return request; }
void Strategy::writeOp(OperationContext* txn, int op, Request& request) { // make sure we have a last error dassert(&LastError::get(cc())); OwnedPointerVector<BatchedCommandRequest> commandRequestsOwned; vector<BatchedCommandRequest*>& commandRequests = commandRequestsOwned.mutableVector(); msgToBatchRequests(request.m(), &commandRequests); for (vector<BatchedCommandRequest*>::iterator it = commandRequests.begin(); it != commandRequests.end(); ++it) { // Multiple commands registered to last error as multiple requests if (it != commandRequests.begin()) LastError::get(cc()).startRequest(); BatchedCommandRequest* commandRequest = *it; // Adjust namespaces for command NamespaceString fullNS(commandRequest->getNS()); string cmdNS = fullNS.getCommandNS(); // We only pass in collection name to command commandRequest->setNS(fullNS); BSONObjBuilder builder; BSONObj requestBSON = commandRequest->toBSON(); { // Disable the last error object for the duration of the write cmd LastError::Disabled disableLastError(&LastError::get(cc())); Command::runAgainstRegistered(txn, cmdNS.c_str(), requestBSON, builder, 0); } BatchedCommandResponse commandResponse; bool parsed = commandResponse.parseBSON(builder.done(), NULL); (void)parsed; // for compile dassert(parsed && commandResponse.isValid(NULL)); // Populate the lastError object based on the write response LastError::get(cc()).reset(); bool hadError = batchErrorToLastError(*commandRequest, commandResponse, &LastError::get(cc())); // Check if this is an ordered batch and we had an error which should stop processing if (commandRequest->getOrdered() && hadError) break; } }
void msgToBatchInserts( const Message& insertMsg, vector<BatchedCommandRequest*>* insertRequests ) { // Parsing DbMessage throws DbMessage dbMsg( insertMsg ); NamespaceString nss( dbMsg.getns() ); // Continue-on-error == unordered bool coe = dbMsg.reservedField() & Reserved_InsertOption_ContinueOnError; bool ordered = !coe; while ( insertRequests->empty() || dbMsg.moreJSObjs() ) { // Collect docs for next batch, but don't exceed maximum size int totalInsertSize = 0; vector<BSONObj> docs; do { const char* prevObjMark = dbMsg.markGet(); BSONObj nextObj = dbMsg.nextJsObj(); if ( totalInsertSize + nextObj.objsize() <= BSONObjMaxUserSize ) { docs.push_back( nextObj ); totalInsertSize += docs.back().objsize(); } else { // Size limit exceeded, rollback to previous insert position dbMsg.markReset( prevObjMark ); break; } } while ( dbMsg.moreJSObjs() ); dassert( !docs.empty() ); // No exceptions from here on BatchedCommandRequest* request = new BatchedCommandRequest( BatchedCommandRequest::BatchType_Insert ); request->setNS( nss.ns() ); for ( vector<BSONObj>::const_iterator it = docs.begin(); it != docs.end(); ++it ) { request->getInsertRequest()->addToDocuments( *it ); } request->setOrdered( ordered ); insertRequests->push_back( request ); } }
BatchedCommandRequest* msgToBatchDelete( const Message& deleteMsg ) { // Parsing DbMessage throws DbMessage dbMsg( deleteMsg ); NamespaceString nss( dbMsg.getns() ); int flags = dbMsg.pullInt(); const BSONObj query = dbMsg.nextJsObj(); int limit = ( flags & RemoveOption_JustOne ) ? 1 : 0; // No exceptions from here on BatchedDeleteDocument* deleteDoc = new BatchedDeleteDocument; deleteDoc->setLimit( limit ); deleteDoc->setQuery( query ); BatchedCommandRequest* request = new BatchedCommandRequest( BatchedCommandRequest::BatchType_Delete ); request->setNS( nss.ns() ); request->getDeleteRequest()->addToDeletes( deleteDoc ); return request; }