void WriteBatchExecutor::incOpStats( const BatchItemRef& currWrite ) { if ( currWrite.getOpType() == BatchedCommandRequest::BatchType_Insert ) { _opCounters->gotInsert(); } else if ( currWrite.getOpType() == BatchedCommandRequest::BatchType_Update ) { _opCounters->gotUpdate(); } else { dassert( currWrite.getOpType() == BatchedCommandRequest::BatchType_Delete ); _opCounters->gotDelete(); } }
void WriteBatchExecutor::incOpStats( const BatchItemRef& currWrite ) { if ( currWrite.getOpType() == BatchedCommandRequest::BatchType_Insert ) { // No-op, for inserts we increment not on the op but once for each write } else if ( currWrite.getOpType() == BatchedCommandRequest::BatchType_Update ) { _opCounters->gotUpdate(); } else { dassert( currWrite.getOpType() == BatchedCommandRequest::BatchType_Delete ); _opCounters->gotDelete(); } }
void WriteBatchExecutor::incWriteStats( const BatchItemRef& currWrite, const WriteOpStats& stats, const WriteErrorDetail* error, CurOp* currentOp ) { if ( currWrite.getOpType() == BatchedCommandRequest::BatchType_Insert ) { // We increment batch inserts like individual inserts _opCounters->gotInsert(); _stats->numInserted += stats.n; _le->nObjects = stats.n; currentOp->debug().ninserted += stats.n; } else if ( currWrite.getOpType() == BatchedCommandRequest::BatchType_Update ) { if ( stats.upsertedID.isEmpty() ) { _stats->numMatched += stats.n; _stats->numModified += stats.nModified; } else { ++_stats->numUpserted; } if ( !error ) { _le->recordUpdate( stats.upsertedID.isEmpty() && stats.n > 0, stats.n, stats.upsertedID ); } } else { dassert( currWrite.getOpType() == BatchedCommandRequest::BatchType_Delete ); _stats->numDeleted += stats.n; if ( !error ) { _le->recordDelete( stats.n ); } currentOp->debug().ndeleted += stats.n; } // Errors reported in LastError are handled internally in write ops for now // TODO: Move error reporting out of write op internals? }
void WriteBatchExecutor::incWriteStats( const BatchItemRef& currWrite, const WriteOpStats& stats, const WriteErrorDetail* error, CurOp* currentOp ) { if ( currWrite.getOpType() == BatchedCommandRequest::BatchType_Insert ) { _stats->numInserted += stats.n; _le->nObjects = stats.n; currentOp->debug().ninserted += stats.n; } else if ( currWrite.getOpType() == BatchedCommandRequest::BatchType_Update ) { if ( stats.upsertedID.isEmpty() ) { _stats->numMatched += stats.n; _stats->numModified += stats.nModified; } else { ++_stats->numUpserted; } if ( !error ) { _le->recordUpdate( stats.upsertedID.isEmpty() && stats.n > 0, stats.n, stats.upsertedID ); } } else { dassert( currWrite.getOpType() == BatchedCommandRequest::BatchType_Delete ); _stats->numDeleted += stats.n; if ( !error ) { _le->recordDelete( stats.n ); } currentOp->debug().ndeleted += stats.n; } if (error && !_le->disabled) { _le->raiseError(error->getErrCode(), error->getErrMessage().c_str()); } }
Status Strategy::commandOpWrite(const std::string& dbName, const BSONObj& command, BatchItemRef targetingBatchItem, std::vector<CommandResult>* results) { // Note that this implementation will not handle targeting retries and does not completely // emulate write behavior ChunkManagerTargeter targeter(NamespaceString( targetingBatchItem.getRequest()->getTargetingNS())); Status status = targeter.init(); if (!status.isOK()) return status; OwnedPointerVector<ShardEndpoint> endpointsOwned; vector<ShardEndpoint*>& endpoints = endpointsOwned.mutableVector(); if (targetingBatchItem.getOpType() == BatchedCommandRequest::BatchType_Insert) { ShardEndpoint* endpoint; Status status = targeter.targetInsert(targetingBatchItem.getDocument(), &endpoint); if (!status.isOK()) return status; endpoints.push_back(endpoint); } else if (targetingBatchItem.getOpType() == BatchedCommandRequest::BatchType_Update) { Status status = targeter.targetUpdate(*targetingBatchItem.getUpdate(), &endpoints); if (!status.isOK()) return status; } else { invariant(targetingBatchItem.getOpType() == BatchedCommandRequest::BatchType_Delete); Status status = targeter.targetDelete(*targetingBatchItem.getDelete(), &endpoints); if (!status.isOK()) return status; } DBClientShardResolver resolver; DBClientMultiCommand dispatcher; // Assemble requests for (vector<ShardEndpoint*>::const_iterator it = endpoints.begin(); it != endpoints.end(); ++it) { const ShardEndpoint* endpoint = *it; ConnectionString host; Status status = resolver.chooseWriteHost(endpoint->shardName, &host); if (!status.isOK()) return status; RawBSONSerializable request(command); dispatcher.addCommand(host, dbName, request); } // Errors reported when recv'ing responses dispatcher.sendAll(); Status dispatchStatus = Status::OK(); // Recv responses while (dispatcher.numPending() > 0) { ConnectionString host; RawBSONSerializable response; Status status = dispatcher.recvAny(&host, &response); if (!status.isOK()) { // We always need to recv() all the sent operations dispatchStatus = status; continue; } CommandResult result; result.target = host; result.shardTarget = Shard::make(host.toString()); result.result = response.toBSON(); results->push_back(result); } return dispatchStatus; }