diff options
Diffstat (limited to 'src/mongo/s/commands/cluster_find_and_modify_cmd.cpp')
-rw-r--r-- | src/mongo/s/commands/cluster_find_and_modify_cmd.cpp | 285 |
1 files changed, 137 insertions, 148 deletions
diff --git a/src/mongo/s/commands/cluster_find_and_modify_cmd.cpp b/src/mongo/s/commands/cluster_find_and_modify_cmd.cpp index 8fcff46f1cd..4f14f66fe2c 100644 --- a/src/mongo/s/commands/cluster_find_and_modify_cmd.cpp +++ b/src/mongo/s/commands/cluster_find_and_modify_cmd.cpp @@ -49,192 +49,181 @@ namespace mongo { namespace { - using std::shared_ptr; - using std::string; - using std::vector; +using std::shared_ptr; +using std::string; +using std::vector; - class FindAndModifyCmd : public Command { - public: - FindAndModifyCmd() : Command("findAndModify", false, "findandmodify") { } +class FindAndModifyCmd : public Command { +public: + FindAndModifyCmd() : Command("findAndModify", false, "findandmodify") {} - virtual bool slaveOk() const { - return true; - } - - virtual bool adminOnly() const { - return false; - } - - virtual bool isWriteCommandForConfigServer() const { - return false; - } - - virtual void addRequiredPrivileges(const std::string& dbname, - const BSONObj& cmdObj, - std::vector<Privilege>* out) { - - find_and_modify::addPrivilegesRequiredForFindAndModify(this, dbname, cmdObj, out); - } - - virtual Status explain(OperationContext* txn, - const std::string& dbName, - const BSONObj& cmdObj, - ExplainCommon::Verbosity verbosity, - BSONObjBuilder* out) const { - - const string ns = parseNsCollectionRequired(dbName, cmdObj); - - auto status = grid.catalogCache()->getDatabase(dbName); - uassertStatusOK(status); + virtual bool slaveOk() const { + return true; + } - shared_ptr<DBConfig> conf = status.getValue(); + virtual bool adminOnly() const { + return false; + } - shared_ptr<Shard> shard; + virtual bool isWriteCommandForConfigServer() const { + return false; + } - if (!conf->isShardingEnabled() || !conf->isSharded(ns)) { - shard = grid.shardRegistry()->getShard(conf->getPrimaryId()); - } - else { - shared_ptr<ChunkManager> chunkMgr = _getChunkManager(conf, ns); - - const BSONObj query = cmdObj.getObjectField("query"); - - StatusWith<BSONObj> status = _getShardKey(chunkMgr, query); - if (!status.isOK()) { - return status.getStatus(); - } - - BSONObj shardKey = status.getValue(); - ChunkPtr chunk = chunkMgr->findIntersectingChunk(shardKey); - - shard = grid.shardRegistry()->getShard(chunk->getShardId()); - } + virtual void addRequiredPrivileges(const std::string& dbname, + const BSONObj& cmdObj, + std::vector<Privilege>* out) { + find_and_modify::addPrivilegesRequiredForFindAndModify(this, dbname, cmdObj, out); + } - BSONObjBuilder explainCmd; - ClusterExplain::wrapAsExplain(cmdObj, verbosity, &explainCmd); + virtual Status explain(OperationContext* txn, + const std::string& dbName, + const BSONObj& cmdObj, + ExplainCommon::Verbosity verbosity, + BSONObjBuilder* out) const { + const string ns = parseNsCollectionRequired(dbName, cmdObj); - // Time how long it takes to run the explain command on the shard. - Timer timer; + auto status = grid.catalogCache()->getDatabase(dbName); + uassertStatusOK(status); - BSONObjBuilder result; - bool ok = _runCommand(conf, shard->getId(), ns, explainCmd.obj(), result); - long long millisElapsed = timer.millis(); + shared_ptr<DBConfig> conf = status.getValue(); - if (!ok) { - BSONObj res = result.obj(); - return Status(ErrorCodes::OperationFailed, - str::stream() << "Explain for findAndModify failed: " << res); - } - - Strategy::CommandResult cmdResult; - cmdResult.shardTargetId = shard->getId(); - cmdResult.target = shard->getConnString(); - cmdResult.result = result.obj(); - - vector<Strategy::CommandResult> shardResults; - shardResults.push_back(cmdResult); - - return ClusterExplain::buildExplainResult(shardResults, - ClusterExplain::kSingleShard, - millisElapsed, - out); - } - - virtual bool run(OperationContext* txn, - const std::string& dbName, - BSONObj& cmdObj, - int options, - std::string& errmsg, - BSONObjBuilder& result) { - - const string ns = parseNsCollectionRequired(dbName, cmdObj); - - // findAndModify should only be creating database if upsert is true, but this would - // require that the parsing be pulled into this function. - auto conf = uassertStatusOK(grid.implicitCreateDb(dbName)); - if (!conf->isShardingEnabled() || !conf->isSharded(ns)) { - return _runCommand(conf, conf->getPrimaryId(), ns, cmdObj, result); - } + shared_ptr<Shard> shard; + if (!conf->isShardingEnabled() || !conf->isSharded(ns)) { + shard = grid.shardRegistry()->getShard(conf->getPrimaryId()); + } else { shared_ptr<ChunkManager> chunkMgr = _getChunkManager(conf, ns); const BSONObj query = cmdObj.getObjectField("query"); StatusWith<BSONObj> status = _getShardKey(chunkMgr, query); if (!status.isOK()) { - // Bad query - return appendCommandStatus(result, status.getStatus()); + return status.getStatus(); } BSONObj shardKey = status.getValue(); ChunkPtr chunk = chunkMgr->findIntersectingChunk(shardKey); - bool ok = _runCommand(conf, chunk->getShardId(), ns, cmdObj, result); - if (ok) { - // check whether split is necessary (using update object for size heuristic) - if (Chunk::ShouldAutoSplit) { - chunk->splitIfShould(cmdObj.getObjectField("update").objsize()); - } - } - - return ok; + shard = grid.shardRegistry()->getShard(chunk->getShardId()); } - private: - shared_ptr<ChunkManager> _getChunkManager(shared_ptr<DBConfig> conf, - const string& ns) const { + BSONObjBuilder explainCmd; + ClusterExplain::wrapAsExplain(cmdObj, verbosity, &explainCmd); - shared_ptr<ChunkManager> chunkMgr = conf->getChunkManager(ns); - massert(13002, "shard internal error chunk manager should never be null", chunkMgr); + // Time how long it takes to run the explain command on the shard. + Timer timer; - return chunkMgr; + BSONObjBuilder result; + bool ok = _runCommand(conf, shard->getId(), ns, explainCmd.obj(), result); + long long millisElapsed = timer.millis(); + + if (!ok) { + BSONObj res = result.obj(); + return Status(ErrorCodes::OperationFailed, + str::stream() << "Explain for findAndModify failed: " << res); } - StatusWith<BSONObj> _getShardKey(shared_ptr<ChunkManager> chunkMgr, - const BSONObj& query) const { + Strategy::CommandResult cmdResult; + cmdResult.shardTargetId = shard->getId(); + cmdResult.target = shard->getConnString(); + cmdResult.result = result.obj(); + + vector<Strategy::CommandResult> shardResults; + shardResults.push_back(cmdResult); + + return ClusterExplain::buildExplainResult( + shardResults, ClusterExplain::kSingleShard, millisElapsed, out); + } + + virtual bool run(OperationContext* txn, + const std::string& dbName, + BSONObj& cmdObj, + int options, + std::string& errmsg, + BSONObjBuilder& result) { + const string ns = parseNsCollectionRequired(dbName, cmdObj); + + // findAndModify should only be creating database if upsert is true, but this would + // require that the parsing be pulled into this function. + auto conf = uassertStatusOK(grid.implicitCreateDb(dbName)); + if (!conf->isShardingEnabled() || !conf->isSharded(ns)) { + return _runCommand(conf, conf->getPrimaryId(), ns, cmdObj, result); + } - // Verify that the query has an equality predicate using the shard key - StatusWith<BSONObj> status = - chunkMgr->getShardKeyPattern().extractShardKeyFromQuery(query); + shared_ptr<ChunkManager> chunkMgr = _getChunkManager(conf, ns); - if (!status.isOK()) { - return status; - } + const BSONObj query = cmdObj.getObjectField("query"); - BSONObj shardKey = status.getValue(); + StatusWith<BSONObj> status = _getShardKey(chunkMgr, query); + if (!status.isOK()) { + // Bad query + return appendCommandStatus(result, status.getStatus()); + } - if (shardKey.isEmpty()) { - return Status(ErrorCodes::ShardKeyNotFound, - "query for sharded findAndModify must have shardkey"); - } + BSONObj shardKey = status.getValue(); + ChunkPtr chunk = chunkMgr->findIntersectingChunk(shardKey); - return shardKey; + bool ok = _runCommand(conf, chunk->getShardId(), ns, cmdObj, result); + if (ok) { + // check whether split is necessary (using update object for size heuristic) + if (Chunk::ShouldAutoSplit) { + chunk->splitIfShould(cmdObj.getObjectField("update").objsize()); + } } - bool _runCommand(DBConfigPtr conf, - const ShardId& shardId, - const string& ns, - const BSONObj& cmdObj, - BSONObjBuilder& result) const { + return ok; + } - BSONObj res; +private: + shared_ptr<ChunkManager> _getChunkManager(shared_ptr<DBConfig> conf, const string& ns) const { + shared_ptr<ChunkManager> chunkMgr = conf->getChunkManager(ns); + massert(13002, "shard internal error chunk manager should never be null", chunkMgr); - const auto shard = grid.shardRegistry()->getShard(shardId); - ShardConnection conn(shard->getConnString(), ns); - bool ok = conn->runCommand(conf->name(), cmdObj, res); - conn.done(); + return chunkMgr; + } - // RecvStaleConfigCode is the code for RecvStaleConfigException. - if (!ok && res.getIntField("code") == RecvStaleConfigCode) { - // Command code traps this exception and re-runs - throw RecvStaleConfigException("FindAndModify", res); - } + StatusWith<BSONObj> _getShardKey(shared_ptr<ChunkManager> chunkMgr, + const BSONObj& query) const { + // Verify that the query has an equality predicate using the shard key + StatusWith<BSONObj> status = chunkMgr->getShardKeyPattern().extractShardKeyFromQuery(query); + + if (!status.isOK()) { + return status; + } + + BSONObj shardKey = status.getValue(); - result.appendElements(res); - return ok; + if (shardKey.isEmpty()) { + return Status(ErrorCodes::ShardKeyNotFound, + "query for sharded findAndModify must have shardkey"); } - } findAndModifyCmd; + return shardKey; + } + + bool _runCommand(DBConfigPtr conf, + const ShardId& shardId, + const string& ns, + const BSONObj& cmdObj, + BSONObjBuilder& result) const { + BSONObj res; + + const auto shard = grid.shardRegistry()->getShard(shardId); + ShardConnection conn(shard->getConnString(), ns); + bool ok = conn->runCommand(conf->name(), cmdObj, res); + conn.done(); + + // RecvStaleConfigCode is the code for RecvStaleConfigException. + if (!ok && res.getIntField("code") == RecvStaleConfigCode) { + // Command code traps this exception and re-runs + throw RecvStaleConfigException("FindAndModify", res); + } + + result.appendElements(res); + return ok; + } + +} findAndModifyCmd; -} // namespace -} // namespace mongo +} // namespace +} // namespace mongo |