Ejemplo n.º 1
0
    void BatchWriteOp::buildClientResponse( BatchedCommandResponse* batchResp ) {

        dassert( isFinished() );

        //
        // Find all the errors in the batch
        //

        vector<WriteOp*> errOps;

        size_t numWriteOps = _clientRequest->sizeWriteOps();
        for ( size_t i = 0; i < numWriteOps; ++i ) {

            WriteOp& writeOp = _writeOps[i];

            if ( writeOp.getWriteState() == WriteOpState_Error ) {
                errOps.push_back( &writeOp );
            }
        }

        //
        // Build the top-level batch error
        // This will be either the write concern error, the special "multiple item errors" error,
        // or a promoted single-item error.  Top-level parsing/targeting errors handled elsewhere.
        //

        if ( !_wcErrors.empty() ) {
            BatchedErrorDetail comboWCError;
            combineWCErrors( _wcErrors.vector(), &comboWCError );
            cloneBatchErrorFrom( comboWCError, batchResp );
        }
        else if ( !errOps.empty() ) {
            BatchedErrorDetail comboBatchError;
            combineOpErrors( errOps, &comboBatchError );
            cloneBatchErrorFrom( comboBatchError, batchResp );

            // Suppress further error details if only one error
            if ( _clientRequest->sizeWriteOps() == 1u ) errOps.clear();
        }

        //
        // Build the per-item errors, if needed
        //

        if ( !errOps.empty() ) {
            for ( vector<WriteOp*>::iterator it = errOps.begin(); it != errOps.end(); ++it ) {
                WriteOp& writeOp = **it;
                BatchedErrorDetail* error = new BatchedErrorDetail();
                writeOp.getOpError().cloneTo( error );
                batchResp->addToErrDetails( error );
            }
        }

        batchResp->setOk( !batchResp->isErrCodeSet() );
    }
Ejemplo n.º 2
0
    /**
     * This is the core function which aggregates all the results of a write operation on multiple
     * shards and updates the write operation's state.
     */
    void WriteOp::updateOpState() {

        vector<ChildWriteOp*> childErrors;

        bool isRetryError = true;
        for ( vector<ChildWriteOp*>::iterator it = _childOps.begin(); it != _childOps.end();
            it++ ) {

            ChildWriteOp* childOp = *it;

            // Don't do anything till we have all the info
            if ( childOp->state != WriteOpState_Completed
                 && childOp->state != WriteOpState_Error ) {
                return;
            }

            if ( childOp->state == WriteOpState_Error ) {
                childErrors.push_back( childOp );
                // Any non-retry error aborts all
                if ( !isRetryErrCode( childOp->error->getErrCode() ) ) isRetryError = false;
            }
        }

        if ( !childErrors.empty() && isRetryError ) {
            // Since we're using broadcast mode for multi-shard writes, which cannot SCE
            dassert( childErrors.size() == 1u );
            _state = WriteOpState_Ready;
        }
        else if ( !childErrors.empty() ) {
            _error.reset( new BatchedErrorDetail );
            combineOpErrors( childErrors, _error.get() );
            _state = WriteOpState_Error;
        }
        else {
            _state = WriteOpState_Completed;
        }

        // Now that we're done with the child ops, do something with them
        // TODO: Don't store unlimited history?
        dassert( _state != WriteOpState_Pending );
        _history.insert( _history.end(), _childOps.begin(), _childOps.end() );
        _childOps.clear();
    }