Status WriteOp::targetWrites( const NSTargeter& targeter, std::vector<TargetedWrite*>* targetedWrites ) { bool isUpdate = _itemRef.getOpType() == BatchedCommandRequest::BatchType_Update; bool isDelete = _itemRef.getOpType() == BatchedCommandRequest::BatchType_Delete; // In case of error, don't leak. OwnedPointerVector<ShardEndpoint> endpointsOwned; vector<ShardEndpoint*>& endpoints = endpointsOwned.mutableVector(); if ( isUpdate || isDelete ) { // Updates/deletes targeted by query BSONObj queryDoc = isUpdate ? _itemRef.getUpdate()->getQuery() : _itemRef.getDelete()->getQuery(); Status targetStatus = targeter.targetQuery( queryDoc, &endpoints ); if ( targetStatus.isOK() ) { targetStatus = isUpdate ? updateTargetsOk( *this, endpoints ) : deleteTargetsOk( *this, endpoints ); } if ( !targetStatus.isOK() ) return targetStatus; } else { dassert( _itemRef.getOpType() == BatchedCommandRequest::BatchType_Insert ); // Inserts targeted by doc itself ShardEndpoint* endpoint = NULL; Status targetStatus = targeter.targetDoc( _itemRef.getDocument(), &endpoint ); if ( !targetStatus.isOK() ) { dassert( NULL == endpoint ); return targetStatus; } dassert( NULL != endpoint ); endpoints.push_back( endpoint ); } for ( vector<ShardEndpoint*>::iterator it = endpoints.begin(); it != endpoints.end(); ++it ) { ShardEndpoint* endpoint = *it; _childOps.push_back( new ChildWriteOp( this ) ); WriteOpRef ref( _itemRef.getItemIndex(), _childOps.size() - 1 ); // For now, multiple endpoints imply no versioning if ( endpoints.size() == 1u ) { targetedWrites->push_back( new TargetedWrite( *endpoint, ref ) ); } else { ShardEndpoint broadcastEndpoint( endpoint->shardName, ChunkVersion::IGNORED(), endpoint->shardHost ); targetedWrites->push_back( new TargetedWrite( broadcastEndpoint, ref ) ); } _childOps.back()->pendingWrite = targetedWrites->back(); _childOps.back()->state = WriteOpState_Pending; } _state = WriteOpState_Pending; return Status::OK(); }
Status WriteOp::targetWrites( const NSTargeter& targeter, std::vector<TargetedWrite*>* targetedWrites ) { bool isUpdate = _itemRef.getOpType() == BatchedCommandRequest::BatchType_Update; bool isDelete = _itemRef.getOpType() == BatchedCommandRequest::BatchType_Delete; bool isIndexInsert = _itemRef.getRequest()->isInsertIndexRequest(); Status targetStatus = Status::OK(); OwnedPointerVector<ShardEndpoint> endpointsOwned; vector<ShardEndpoint*>& endpoints = endpointsOwned.mutableVector(); if ( isUpdate ) { targetStatus = targeter.targetUpdate( *_itemRef.getUpdate(), &endpoints ); } else if ( isDelete ) { targetStatus = targeter.targetDelete( *_itemRef.getDelete(), &endpoints ); } else { dassert( _itemRef.getOpType() == BatchedCommandRequest::BatchType_Insert ); ShardEndpoint* endpoint = NULL; // TODO: Remove the index targeting stuff once there is a command for it if ( !isIndexInsert ) { targetStatus = targeter.targetInsert( _itemRef.getDocument(), &endpoint ); } else { // TODO: Retry index writes with stale version? targetStatus = targeter.targetAll( &endpoints ); } if ( !targetStatus.isOK() ) { dassert( NULL == endpoint ); return targetStatus; } // Store single endpoint result if we targeted a single endpoint if ( endpoint ) endpoints.push_back( endpoint ); } // If we had an error, stop here if ( !targetStatus.isOK() ) return targetStatus; for ( vector<ShardEndpoint*>::iterator it = endpoints.begin(); it != endpoints.end(); ++it ) { ShardEndpoint* endpoint = *it; _childOps.push_back( new ChildWriteOp( this ) ); WriteOpRef ref( _itemRef.getItemIndex(), _childOps.size() - 1 ); // For now, multiple endpoints imply no versioning if ( endpoints.size() == 1u ) { targetedWrites->push_back( new TargetedWrite( *endpoint, ref ) ); } else { ShardEndpoint broadcastEndpoint( endpoint->shardName, ChunkVersion::IGNORED() ); targetedWrites->push_back( new TargetedWrite( broadcastEndpoint, ref ) ); } _childOps.back()->pendingWrite = targetedWrites->back(); _childOps.back()->state = WriteOpState_Pending; } _state = WriteOpState_Pending; return Status::OK(); }