summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mongo/s/chunk_manager_targeter.cpp27
-rw-r--r--src/mongo/s/chunk_manager_targeter.h13
-rw-r--r--src/mongo/s/mock_ns_targeter.h58
-rw-r--r--src/mongo/s/ns_targeter.h17
-rw-r--r--src/mongo/s/write_op.cpp21
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;