diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/s/chunk_manager_targeter.cpp | 27 | ||||
-rw-r--r-- | src/mongo/s/chunk_manager_targeter.h | 13 | ||||
-rw-r--r-- | src/mongo/s/mock_ns_targeter.h | 58 | ||||
-rw-r--r-- | src/mongo/s/ns_targeter.h | 17 | ||||
-rw-r--r-- | src/mongo/s/write_op.cpp | 21 |
5 files changed, 103 insertions, 33 deletions
diff --git a/src/mongo/s/chunk_manager_targeter.cpp b/src/mongo/s/chunk_manager_targeter.cpp index f864c00bd01..d64f031a197 100644 --- a/src/mongo/s/chunk_manager_targeter.cpp +++ b/src/mongo/s/chunk_manager_targeter.cpp @@ -107,6 +107,33 @@ namespace mongo { return Status::OK(); } + Status ChunkManagerTargeter::targetUpdate( const BSONObj& query, + const BSONObj& update, + vector<ShardEndpoint*>* endpoints ) const { + // Pre-2.6 implementation differentiates between $op and replacement style and + // will use the update object for routing as well as deciding which chunk will have + // their size stats incremented. Here, the query object is always used. + Status result = targetQuery( query, endpoints ); + + if ( result.isOK() ) { + if ( !_manager->hasShardKey( query )) { + return result; + } + + // Note: this is only best effort accounting and is not accurate. + ChunkPtr chunk = _manager->findChunkForDoc( query ); + _stats->chunkSizeDelta[chunk->getMin()] += (query.objsize() + update.objsize()); + } + + return result; + } + + Status ChunkManagerTargeter::targetDelete( const BSONObj& query, + vector<ShardEndpoint*>* endpoints ) const { + return targetQuery( query, endpoints ); + } + + Status ChunkManagerTargeter::targetQuery( const BSONObj& query, vector<ShardEndpoint*>* endpoints ) const { diff --git a/src/mongo/s/chunk_manager_targeter.h b/src/mongo/s/chunk_manager_targeter.h index d30e775c82c..03bcc4efbdf 100644 --- a/src/mongo/s/chunk_manager_targeter.h +++ b/src/mongo/s/chunk_manager_targeter.h @@ -52,7 +52,11 @@ namespace mongo { Status targetDoc( const BSONObj& doc, ShardEndpoint** endpoint ) const; - Status targetQuery( const BSONObj& query, std::vector<ShardEndpoint*>* endpoints ) const; + Status targetUpdate( const BSONObj& query, + const BSONObj& update, + std::vector<ShardEndpoint*>* endpoints ) const; + + Status targetDelete( const BSONObj& query, std::vector<ShardEndpoint*>* endpoints ) const; void noteStaleResponse( const ShardEndpoint& endpoint, const BSONObj& staleInfo ); @@ -90,6 +94,13 @@ namespace mongo { */ Status refreshNow( RefreshType refreshType ); + /** + * Returns a vector of ShardEndpoints for a potentially multi-shard query. + * + * Returns !OK with message if query could not be targeted. + */ + Status targetQuery( const BSONObj& query, std::vector<ShardEndpoint*>* endpoints ) const; + NamespaceString _nss; // Zero or one of these are filled at all times diff --git a/src/mongo/s/mock_ns_targeter.h b/src/mongo/s/mock_ns_targeter.h index 3cc1874e635..e15d2f6ec35 100644 --- a/src/mongo/s/mock_ns_targeter.h +++ b/src/mongo/s/mock_ns_targeter.h @@ -112,27 +112,18 @@ namespace mongo { * Returns the first ShardEndpoint for the query from the mock ranges. Only can handle * queries of the form { field : { $gte : <value>, $lt : <value> } }. */ - Status targetQuery( const BSONObj& query, std::vector<ShardEndpoint*>* endpoints ) const { - - KeyRange queryRange = parseRange( query ); - - const std::vector<MockRange*>& ranges = getRanges(); - for ( std::vector<MockRange*>::const_iterator it = ranges.begin(); it != ranges.end(); - ++it ) { - - const MockRange* range = *it; - - if ( rangeOverlaps( queryRange.minKey, - queryRange.maxKey, - range->range.minKey, - range->range.maxKey ) ) { - endpoints->push_back( new ShardEndpoint( range->endpoint ) ); - } - } + Status targetUpdate( const BSONObj& query, + const BSONObj& update, + std::vector<ShardEndpoint*>* endpoints ) const { + return targetQuery( query, endpoints ); + } - if ( endpoints->empty() ) return Status( ErrorCodes::UnknownError, - "no mock ranges found for query" ); - return Status::OK(); + /** + * Returns the first ShardEndpoint for the query from the mock ranges. Only can handle + * queries of the form { field : { $gte : <value>, $lt : <value> } }. + */ + Status targetDelete( const BSONObj& query, std::vector<ShardEndpoint*>* endpoints ) const { + return targetQuery( query, endpoints ); } void noteCouldNotTarget() { @@ -173,6 +164,33 @@ namespace mongo { return KeyRange( "", minKeyB.obj(), maxKeyB.obj(), BSON( fieldName << 1 ) ); } + /** + * Returns the first ShardEndpoint for the query from the mock ranges. Only can handle + * queries of the form { field : { $gte : <value>, $lt : <value> } }. + */ + Status targetQuery( const BSONObj& query, std::vector<ShardEndpoint*>* endpoints ) const { + + KeyRange queryRange = parseRange( query ); + + const std::vector<MockRange*>& ranges = getRanges(); + for ( std::vector<MockRange*>::const_iterator it = ranges.begin(); it != ranges.end(); + ++it ) { + + const MockRange* range = *it; + + if ( rangeOverlaps( queryRange.minKey, + queryRange.maxKey, + range->range.minKey, + range->range.maxKey ) ) { + endpoints->push_back( new ShardEndpoint( range->endpoint ) ); + } + } + + if ( endpoints->empty() ) return Status( ErrorCodes::UnknownError, + "no mock ranges found for query" ); + return Status::OK(); + } + NamespaceString _nss; // Manually-stored ranges diff --git a/src/mongo/s/ns_targeter.h b/src/mongo/s/ns_targeter.h index 84b74bf9a4e..4fd5b16b17a 100644 --- a/src/mongo/s/ns_targeter.h +++ b/src/mongo/s/ns_targeter.h @@ -85,12 +85,21 @@ namespace mongo { virtual Status targetDoc( const BSONObj& doc, ShardEndpoint** endpoint ) const = 0; /** - * Returns a vector of ShardEndpoints for a potentially multi-shard query. + * Returns a vector of ShardEndpoints for a potentially multi-shard update. * - * Returns !OK with message if query could not be targeted. + * Returns OK and fills the endpoints; returns a status describing the error otherwise. */ - virtual Status targetQuery( const BSONObj& query, - std::vector<ShardEndpoint*>* endpoints ) const = 0; + virtual Status targetUpdate( const BSONObj& query, + const BSONObj& update, + std::vector<ShardEndpoint*>* endpoints ) const = 0; + + /** + * Returns a vector of ShardEndpoints for a potentially multi-shard delete. + * + * Returns OK and fills the endpoints; returns a status describing the error otherwise. + */ + virtual Status targetDelete( const BSONObj& query, + std::vector<ShardEndpoint*>* endpoints ) const = 0; /** * Informs the targeter that a targeting failure occurred during one of the last targeting diff --git a/src/mongo/s/write_op.cpp b/src/mongo/s/write_op.cpp index 18f6938586e..79c50124553 100644 --- a/src/mongo/s/write_op.cpp +++ b/src/mongo/s/write_op.cpp @@ -83,19 +83,24 @@ namespace mongo { OwnedPointerVector<ShardEndpoint> endpointsOwned; vector<ShardEndpoint*>& endpoints = endpointsOwned.mutableVector(); - if ( isUpdate || isDelete ) { + if ( isUpdate ) { + Status targetStatus = targeter.targetUpdate( _itemRef.getUpdate()->getQuery(), + _itemRef.getUpdate()->getUpdateExpr(), + &endpoints ); - // Updates/deletes targeted by query + if ( targetStatus.isOK() ) { + targetStatus = updateTargetsOk( *this, endpoints ); + } - BSONObj queryDoc = - isUpdate ? _itemRef.getUpdate()->getQuery() : _itemRef.getDelete()->getQuery(); + if ( !targetStatus.isOK() ) return targetStatus; + } + else if ( isDelete ) { - Status targetStatus = targeter.targetQuery( queryDoc, &endpoints ); + BSONObj queryDoc = _itemRef.getDelete()->getQuery(); + Status targetStatus = targeter.targetDelete( queryDoc, &endpoints ); if ( targetStatus.isOK() ) { - targetStatus = - isUpdate ? - updateTargetsOk( *this, endpoints ) : deleteTargetsOk( *this, endpoints ); + targetStatus = deleteTargetsOk( *this, endpoints ); } if ( !targetStatus.isOK() ) return targetStatus; |