summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mongo/s/SConscript2
-rw-r--r--src/mongo/s/chunk.cpp10
-rw-r--r--src/mongo/s/chunk_manager_targeter.cpp48
-rw-r--r--src/mongo/s/commands/cluster_find_and_modify_cmd.cpp15
-rw-r--r--src/mongo/s/commands/cluster_map_reduce_cmd.cpp5
-rw-r--r--src/mongo/s/commands/cluster_merge_chunks_cmd.cpp4
-rw-r--r--src/mongo/s/commands/cluster_shard_collection_cmd.cpp6
-rw-r--r--src/mongo/s/commands/commands_public.cpp61
-rw-r--r--src/mongo/s/commands/run_on_all_shards_cmd.cpp4
-rw-r--r--src/mongo/s/db_util.cpp61
-rw-r--r--src/mongo/s/db_util.h50
-rw-r--r--src/mongo/s/sharding_raii.cpp109
-rw-r--r--src/mongo/s/sharding_raii.h123
13 files changed, 310 insertions, 188 deletions
diff --git a/src/mongo/s/SConscript b/src/mongo/s/SConscript
index f33c1ca3307..d0be8932793 100644
--- a/src/mongo/s/SConscript
+++ b/src/mongo/s/SConscript
@@ -179,9 +179,9 @@ env.Library(
'chunk.cpp',
'chunk_manager.cpp',
'config.cpp',
- 'db_util.cpp',
'grid.cpp',
'sharding_egress_metadata_hook.cpp',
+ 'sharding_raii.cpp',
'shard_util.cpp',
],
LIBDEPS=[
diff --git a/src/mongo/s/chunk.cpp b/src/mongo/s/chunk.cpp
index b5799714c51..a35dea17787 100644
--- a/src/mongo/s/chunk.cpp
+++ b/src/mongo/s/chunk.cpp
@@ -78,7 +78,7 @@ const uint64_t kTooManySplitPoints = 4;
* Returns true if the chunk was actually moved.
*/
bool tryMoveToOtherShard(OperationContext* txn,
- const ChunkManager& manager,
+ const ChunkManager* manager,
const ChunkType& chunk) {
auto clusterStatsStatus(Balancer::get(txn)->getClusterStatistics()->getStats(txn));
if (!clusterStatsStatus.isOK()) {
@@ -97,13 +97,13 @@ bool tryMoveToOtherShard(OperationContext* txn,
// Reload sharding metadata before starting migration. Only reload the differences though,
// because the entire chunk manager was reloaded during the call to split, which immediately
// precedes this move logic
- shared_ptr<ChunkManager> chunkMgr = manager.reload(txn, false);
+ shared_ptr<ChunkManager> chunkMgr = manager->reload(txn, false);
map<string, vector<ChunkType>> shardToChunkMap;
DistributionStatus::populateShardToChunksMap(clusterStats, *chunkMgr, &shardToChunkMap);
StatusWith<string> tagStatus =
- grid.catalogManager(txn)->getTagForChunk(txn, manager.getns(), chunk);
+ grid.catalogManager(txn)->getTagForChunk(txn, manager->getns(), chunk);
if (!tagStatus.isOK()) {
warning() << "Not auto-moving chunk because of an error encountered while "
<< "checking tag for chunk: " << tagStatus.getStatus();
@@ -154,7 +154,7 @@ bool tryMoveToOtherShard(OperationContext* txn,
}
// update our config
- manager.reload(txn);
+ manager->reload(txn);
return true;
}
@@ -516,7 +516,7 @@ bool Chunk::splitIfShould(OperationContext* txn, long dataWritten) {
chunkToMove.setMin(suggestedMigrateChunk->first);
chunkToMove.setMax(suggestedMigrateChunk->second);
- tryMoveToOtherShard(txn, *_manager, chunkToMove);
+ tryMoveToOtherShard(txn, _manager, chunkToMove);
}
return true;
diff --git a/src/mongo/s/chunk_manager_targeter.cpp b/src/mongo/s/chunk_manager_targeter.cpp
index 739d9c1f9d1..90d1ac9c86f 100644
--- a/src/mongo/s/chunk_manager_targeter.cpp
+++ b/src/mongo/s/chunk_manager_targeter.cpp
@@ -35,11 +35,11 @@
#include <boost/thread/tss.hpp>
#include "mongo/s/chunk.h"
-#include "mongo/s/chunk_manager.h"
#include "mongo/s/client/shard_registry.h"
#include "mongo/s/config.h"
-#include "mongo/s/db_util.h"
#include "mongo/s/grid.h"
+#include "mongo/s/sharding_raii.h"
+#include "mongo/s/shard_key_pattern.h"
#include "mongo/util/log.h"
#include "mongo/util/mongoutils/str.h"
@@ -270,13 +270,13 @@ ChunkManagerTargeter::ChunkManagerTargeter(const NamespaceString& nss, TargeterS
Status ChunkManagerTargeter::init(OperationContext* txn) {
- auto status = dbutil::implicitCreateDb(txn, _nss.db().toString());
- if (!status.isOK()) {
- return status.getStatus();
+ auto dbStatus = ScopedShardDatabase::getOrCreate(txn, _nss.db());
+ if (!dbStatus.isOK()) {
+ return dbStatus.getStatus();
}
- shared_ptr<DBConfig> config = status.getValue();
- config->getChunkManagerOrPrimary(txn, _nss.ns(), _manager, _primary);
+ auto scopedDb = std::move(dbStatus.getValue());
+ scopedDb.db()->getChunkManagerOrPrimary(txn, _nss.ns(), _manager, _primary);
return Status::OK();
}
@@ -625,13 +625,13 @@ Status ChunkManagerTargeter::refreshIfNeeded(OperationContext* txn, bool* wasCha
shared_ptr<ChunkManager> lastManager = _manager;
shared_ptr<Shard> lastPrimary = _primary;
- auto status = dbutil::implicitCreateDb(txn, _nss.db().toString());
- if (!status.isOK()) {
- return status.getStatus();
+ auto dbStatus = ScopedShardDatabase::getOrCreate(txn, _nss.db());
+ if (!dbStatus.isOK()) {
+ return dbStatus.getStatus();
}
- shared_ptr<DBConfig> config = status.getValue();
- config->getChunkManagerOrPrimary(txn, _nss.ns(), _manager, _primary);
+ auto scopedDb = std::move(dbStatus.getValue());
+ scopedDb.db()->getChunkManagerOrPrimary(txn, _nss.ns(), _manager, _primary);
// We now have the latest metadata from the cache.
@@ -686,12 +686,12 @@ Status ChunkManagerTargeter::refreshIfNeeded(OperationContext* txn, bool* wasCha
}
Status ChunkManagerTargeter::refreshNow(OperationContext* txn, RefreshType refreshType) {
- auto status = dbutil::implicitCreateDb(txn, _nss.db().toString());
- if (!status.isOK()) {
- return status.getStatus();
+ auto dbStatus = ScopedShardDatabase::getOrCreate(txn, _nss.db());
+ if (!dbStatus.isOK()) {
+ return dbStatus.getStatus();
}
- shared_ptr<DBConfig> config = status.getValue();
+ auto scopedDb = std::move(dbStatus.getValue());
// Try not to spam the configs
refreshBackoff();
@@ -699,23 +699,23 @@ Status ChunkManagerTargeter::refreshNow(OperationContext* txn, RefreshType refre
// TODO: Improve synchronization and make more explicit
if (refreshType == RefreshType_RefreshChunkManager) {
try {
- // Forces a remote check of the collection info, synchronization between threads
- // happens internally.
- config->getChunkManagerIfExists(txn, _nss.ns(), true);
+ // Forces a remote check of the collection info, synchronization between threads happens
+ // internally
+ scopedDb.db()->getChunkManagerIfExists(txn, _nss.ns(), true);
} catch (const DBException& ex) {
return Status(ErrorCodes::UnknownError, ex.toString());
}
- config->getChunkManagerOrPrimary(txn, _nss.ns(), _manager, _primary);
+
+ scopedDb.db()->getChunkManagerOrPrimary(txn, _nss.ns(), _manager, _primary);
} else if (refreshType == RefreshType_ReloadDatabase) {
try {
- // Dumps the db info, reloads it all, synchronization between threads happens
- // internally.
- config->reload(txn);
+ // Dumps the db info, reloads it all, synchronization between threads happens internally
+ scopedDb.db()->reload(txn);
} catch (const DBException& ex) {
return Status(ErrorCodes::UnknownError, ex.toString());
}
- config->getChunkManagerOrPrimary(txn, _nss.ns(), _manager, _primary);
+ scopedDb.db()->getChunkManagerOrPrimary(txn, _nss.ns(), _manager, _primary);
}
return Status::OK();
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 cf4d5051c93..086375cbd5d 100644
--- a/src/mongo/s/commands/cluster_find_and_modify_cmd.cpp
+++ b/src/mongo/s/commands/cluster_find_and_modify_cmd.cpp
@@ -43,9 +43,9 @@
#include "mongo/s/config.h"
#include "mongo/s/chunk_manager.h"
#include "mongo/s/commands/cluster_explain.h"
-#include "mongo/s/db_util.h"
#include "mongo/s/grid.h"
#include "mongo/s/mongos_options.h"
+#include "mongo/s/sharding_raii.h"
#include "mongo/s/stale_exception.h"
#include "mongo/s/commands/strategy.h"
#include "mongo/s/write_ops/wc_error_detail.h"
@@ -89,10 +89,9 @@ public:
BSONObjBuilder* out) const {
const NamespaceString nss = parseNsCollectionRequired(dbName, cmdObj);
- auto status = Grid::get(txn)->catalogCache()->getDatabase(txn, dbName);
- uassertStatusOK(status);
+ auto scopedDB = uassertStatusOK(ScopedShardDatabase::getExisting(txn, dbName));
+ DBConfig* conf = scopedDB.db();
- shared_ptr<DBConfig> conf = status.getValue();
shared_ptr<ChunkManager> chunkMgr;
shared_ptr<Shard> shard;
@@ -154,7 +153,9 @@ public:
// 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(dbutil::implicitCreateDb(txn, dbName));
+ auto scopedDb = uassertStatusOK(ScopedShardDatabase::getOrCreate(txn, dbName));
+ DBConfig* conf = scopedDb.db();
+
if (!conf->isShardingEnabled() || !conf->isSharded(nss.ns())) {
return _runCommand(txn, conf, nullptr, conf->getPrimaryId(), nss, cmdObj, result);
}
@@ -185,7 +186,7 @@ public:
private:
shared_ptr<ChunkManager> _getChunkManager(OperationContext* txn,
- shared_ptr<DBConfig> conf,
+ DBConfig* conf,
const NamespaceString& nss) const {
shared_ptr<ChunkManager> chunkMgr = conf->getChunkManager(txn, nss.ns());
massert(13002, "shard internal error chunk manager should never be null", chunkMgr);
@@ -213,7 +214,7 @@ private:
}
bool _runCommand(OperationContext* txn,
- shared_ptr<DBConfig> conf,
+ DBConfig* conf,
shared_ptr<ChunkManager> chunkManager,
const ShardId& shardId,
const NamespaceString& nss,
diff --git a/src/mongo/s/commands/cluster_map_reduce_cmd.cpp b/src/mongo/s/commands/cluster_map_reduce_cmd.cpp
index 06449e4d5a7..b5bb4615b75 100644
--- a/src/mongo/s/commands/cluster_map_reduce_cmd.cpp
+++ b/src/mongo/s/commands/cluster_map_reduce_cmd.cpp
@@ -49,9 +49,9 @@
#include "mongo/s/config.h"
#include "mongo/s/catalog/dist_lock_manager.h"
#include "mongo/s/client/shard_registry.h"
-#include "mongo/s/db_util.h"
#include "mongo/s/grid.h"
#include "mongo/s/commands/strategy.h"
+#include "mongo/s/sharding_raii.h"
#include "mongo/s/write_ops/wc_error_detail.h"
#include "mongo/stdx/chrono.h"
#include "mongo/util/log.h"
@@ -238,7 +238,8 @@ public:
shared_ptr<DBConfig> confOut;
if (customOutDB) {
// Create the output database implicitly, since we have a custom output requested
- confOut = uassertStatusOK(dbutil::implicitCreateDb(txn, outDB));
+ auto scopedDb = uassertStatusOK(ScopedShardDatabase::getOrCreate(txn, outDB));
+ confOut = scopedDb.getSharedDbReference();
} else {
confOut = confIn;
}
diff --git a/src/mongo/s/commands/cluster_merge_chunks_cmd.cpp b/src/mongo/s/commands/cluster_merge_chunks_cmd.cpp
index 2138151321e..be33df99fc5 100644
--- a/src/mongo/s/commands/cluster_merge_chunks_cmd.cpp
+++ b/src/mongo/s/commands/cluster_merge_chunks_cmd.cpp
@@ -150,7 +150,7 @@ public:
}
// This refreshes the chunk metadata if stale.
- ChunkManagerPtr manager = config->getChunkManagerIfExists(txn, nss.ns(), true);
+ shared_ptr<ChunkManager> manager = config->getChunkManagerIfExists(txn, nss.ns(), true);
if (!manager) {
return appendCommandStatus(
result,
@@ -169,7 +169,7 @@ public:
minKey = manager->getShardKeyPattern().normalizeShardKey(minKey);
maxKey = manager->getShardKeyPattern().normalizeShardKey(maxKey);
- ChunkPtr firstChunk = manager->findIntersectingChunk(txn, minKey);
+ shared_ptr<Chunk> firstChunk = manager->findIntersectingChunk(txn, minKey);
verify(firstChunk);
BSONObjBuilder remoteCmdObjB;
diff --git a/src/mongo/s/commands/cluster_shard_collection_cmd.cpp b/src/mongo/s/commands/cluster_shard_collection_cmd.cpp
index ab888d8cc43..d1e834d852d 100644
--- a/src/mongo/s/commands/cluster_shard_collection_cmd.cpp
+++ b/src/mongo/s/commands/cluster_shard_collection_cmd.cpp
@@ -428,7 +428,7 @@ public:
if (isHashedShardKey && isEmpty) {
// Reload the new config info. If we created more than one initial chunk, then
// we need to move them around to balance.
- ChunkManagerPtr chunkManager = config->getChunkManager(txn, ns, true);
+ shared_ptr<ChunkManager> chunkManager = config->getChunkManager(txn, ns, true);
ChunkMap chunkMap = chunkManager->getChunkMap();
// 2. Move and commit each "big chunk" to a different shard.
@@ -440,7 +440,7 @@ public:
continue;
}
- ChunkPtr chunk = c->second;
+ shared_ptr<Chunk> chunk = c->second;
// can't move chunk to shard it's already on
if (to->getId() == chunk->getShardId()) {
@@ -473,7 +473,7 @@ public:
// 3. Subdivide the big chunks by splitting at each of the points in "allSplits"
// that we haven't already split by.
- ChunkPtr currentChunk = chunkManager->findIntersectingChunk(txn, allSplits[0]);
+ shared_ptr<Chunk> currentChunk = chunkManager->findIntersectingChunk(txn, allSplits[0]);
vector<BSONObj> subSplits;
for (unsigned i = 0; i <= allSplits.size(); i++) {
diff --git a/src/mongo/s/commands/commands_public.cpp b/src/mongo/s/commands/commands_public.cpp
index f15d63d65b4..2d1e89d4293 100644
--- a/src/mongo/s/commands/commands_public.cpp
+++ b/src/mongo/s/commands/commands_public.cpp
@@ -55,9 +55,9 @@
#include "mongo/s/commands/run_on_all_shards_cmd.h"
#include "mongo/s/commands/sharded_command_processing.h"
#include "mongo/s/config.h"
-#include "mongo/s/db_util.h"
#include "mongo/s/grid.h"
#include "mongo/s/query/store_possible_cursor.h"
+#include "mongo/s/sharding_raii.h"
#include "mongo/s/stale_exception.h"
#include "mongo/scripting/engine.h"
#include "mongo/util/log.h"
@@ -150,21 +150,21 @@ public:
protected:
bool passthrough(OperationContext* txn,
- shared_ptr<DBConfig> conf,
+ DBConfig* conf,
const BSONObj& cmdObj,
BSONObjBuilder& result) {
return _passthrough(txn, conf->name(), conf, cmdObj, 0, result);
}
bool adminPassthrough(OperationContext* txn,
- shared_ptr<DBConfig> conf,
+ DBConfig* conf,
const BSONObj& cmdObj,
BSONObjBuilder& result) {
return _passthrough(txn, "admin", conf, cmdObj, 0, result);
}
bool passthrough(OperationContext* txn,
- shared_ptr<DBConfig> conf,
+ DBConfig* conf,
const BSONObj& cmdObj,
int options,
BSONObjBuilder& result) {
@@ -174,7 +174,7 @@ protected:
private:
bool _passthrough(OperationContext* txn,
const string& db,
- shared_ptr<DBConfig> conf,
+ DBConfig* conf,
const BSONObj& cmdObj,
int options,
BSONObjBuilder& result) {
@@ -236,7 +236,7 @@ public:
auto conf = uassertStatusOK(grid.catalogCache()->getDatabase(txn, dbName));
if (!conf->isSharded(fullns)) {
- return passthrough(txn, conf, cmdObj, options, result);
+ return passthrough(txn, conf.get(), cmdObj, options, result);
}
return appendCommandStatus(
@@ -434,10 +434,10 @@ public:
auto conf = uassertStatusOK(grid.catalogCache()->getDatabase(txn, dbName));
if (!conf->isShardingEnabled() || !conf->isSharded(nss.ns())) {
- return passthrough(txn, conf, cmdObj, output);
+ return passthrough(txn, conf.get(), cmdObj, output);
}
- ChunkManagerPtr cm = conf->getChunkManager(txn, nss.ns());
+ shared_ptr<ChunkManager> cm = conf->getChunkManager(txn, nss.ns());
massert(40051, "chunk manager should not be null", cm);
vector<Strategy::CommandResult> results;
@@ -510,14 +510,13 @@ public:
int,
string& errmsg,
BSONObjBuilder& result) {
- auto status = dbutil::implicitCreateDb(txn, dbName);
- if (!status.isOK()) {
- return appendCommandStatus(result, status.getStatus());
+ auto dbStatus = ScopedShardDatabase::getOrCreate(txn, dbName);
+ if (!dbStatus.isOK()) {
+ return appendCommandStatus(result, dbStatus.getStatus());
}
- shared_ptr<DBConfig> conf = status.getValue();
-
- return passthrough(txn, conf, cmdObj, result);
+ auto scopedDb = std::move(dbStatus.getValue());
+ return passthrough(txn, scopedDb.db(), cmdObj, result);
}
} createCmd;
@@ -559,7 +558,7 @@ public:
const auto& db = status.getValue();
if (!db->isShardingEnabled() || !db->isSharded(fullns.ns())) {
log() << "\tdrop going to do passthrough";
- return passthrough(txn, db, cmdObj, result);
+ return passthrough(txn, db.get(), cmdObj, result);
}
uassertStatusOK(grid.catalogManager(txn)->dropCollection(txn, fullns));
@@ -609,7 +608,7 @@ public:
"Source and destination collections must be on same shard",
shardFrom == shardTo);
- return adminPassthrough(txn, confFrom, cmdObj, result);
+ return adminPassthrough(txn, confFrom.get(), cmdObj, result);
}
} renameCollectionCmd;
@@ -640,14 +639,14 @@ public:
"invalid todb argument",
NamespaceString::validDBName(todb, NamespaceString::DollarInDbNameBehavior::Allow));
- auto confTo = uassertStatusOK(dbutil::implicitCreateDb(txn, todb));
+ auto scopedToDb = uassertStatusOK(ScopedShardDatabase::getOrCreate(txn, todb));
uassert(ErrorCodes::IllegalOperation,
"cannot copy to a sharded database",
- !confTo->isShardingEnabled());
+ !scopedToDb.db()->isShardingEnabled());
const string fromhost = cmdObj.getStringField("fromhost");
if (!fromhost.empty()) {
- return adminPassthrough(txn, confTo, cmdObj, result);
+ return adminPassthrough(txn, scopedToDb.db(), cmdObj, result);
} else {
const string fromdb = cmdObj.getStringField("fromdb");
uassert(13399, "need a fromdb argument", !fromdb.empty());
@@ -671,7 +670,7 @@ public:
}
BSONObj fixed = b.obj();
- return adminPassthrough(txn, confTo, fixed, result);
+ return adminPassthrough(txn, scopedToDb.db(), fixed, result);
}
}
} clusterCopyDBCmd;
@@ -704,12 +703,12 @@ public:
result.appendBool("sharded", false);
result.append("primary", conf->getPrimaryId());
- return passthrough(txn, conf, cmdObj, result);
+ return passthrough(txn, conf.get(), cmdObj, result);
}
result.appendBool("sharded", true);
- ChunkManagerPtr cm = conf->getChunkManager(txn, fullns);
+ shared_ptr<ChunkManager> cm = conf->getChunkManager(txn, fullns);
massert(12594, "how could chunk manager be null!", cm);
BSONObjBuilder shardStats;
@@ -869,10 +868,10 @@ public:
auto conf = uassertStatusOK(grid.catalogCache()->getDatabase(txn, nsDBName));
if (!conf->isShardingEnabled() || !conf->isSharded(fullns)) {
- return passthrough(txn, conf, cmdObj, result);
+ return passthrough(txn, conf.get(), cmdObj, result);
}
- ChunkManagerPtr cm = conf->getChunkManager(txn, fullns);
+ shared_ptr<ChunkManager> cm = conf->getChunkManager(txn, fullns);
massert(13407, "how could chunk manager be null!", cm);
BSONObj min = cmdObj.getObjectField("min");
@@ -1111,10 +1110,10 @@ public:
shared_ptr<DBConfig> conf = status.getValue();
if (!conf->isShardingEnabled() || !conf->isSharded(fullns)) {
- return passthrough(txn, conf, cmdObj, options, result);
+ return passthrough(txn, conf.get(), cmdObj, options, result);
}
- ChunkManagerPtr cm = conf->getChunkManager(txn, fullns);
+ shared_ptr<ChunkManager> cm = conf->getChunkManager(txn, fullns);
massert(10420, "how could chunk manager be null!", cm);
BSONObj query = getQuery(cmdObj);
@@ -1237,10 +1236,10 @@ public:
auto conf = uassertStatusOK(grid.catalogCache()->getDatabase(txn, dbName));
if (!conf->isShardingEnabled() || !conf->isSharded(fullns)) {
- return passthrough(txn, conf, cmdObj, result);
+ return passthrough(txn, conf.get(), cmdObj, result);
}
- ChunkManagerPtr cm = conf->getChunkManager(txn, fullns);
+ shared_ptr<ChunkManager> cm = conf->getChunkManager(txn, fullns);
massert(13091, "how could chunk manager be null!", cm);
if (cm->getShardKeyPattern().toBSON() == BSON("files_id" << 1)) {
BSONObj finder = BSON("files_id" << cmdObj.firstElement());
@@ -1368,10 +1367,10 @@ public:
auto conf = uassertStatusOK(grid.catalogCache()->getDatabase(txn, dbName));
if (!conf->isShardingEnabled() || !conf->isSharded(fullns)) {
- return passthrough(txn, conf, cmdObj, options, result);
+ return passthrough(txn, conf.get(), cmdObj, options, result);
}
- ChunkManagerPtr cm = conf->getChunkManager(txn, fullns);
+ shared_ptr<ChunkManager> cm = conf->getChunkManager(txn, fullns);
massert(13500, "how could chunk manager be null!", cm);
BSONObj query = getQuery(cmdObj);
@@ -1546,7 +1545,7 @@ public:
}
shared_ptr<DBConfig> conf = status.getValue();
- return passthrough(txn, conf, cmdObj, result);
+ return passthrough(txn, conf.get(), cmdObj, result);
}
} evalCmd;
diff --git a/src/mongo/s/commands/run_on_all_shards_cmd.cpp b/src/mongo/s/commands/run_on_all_shards_cmd.cpp
index e9991643210..6966fc84ec1 100644
--- a/src/mongo/s/commands/run_on_all_shards_cmd.cpp
+++ b/src/mongo/s/commands/run_on_all_shards_cmd.cpp
@@ -40,8 +40,8 @@
#include "mongo/s/client/shard_registry.h"
#include "mongo/s/commands/cluster_commands_common.h"
#include "mongo/s/commands/sharded_command_processing.h"
-#include "mongo/s/db_util.h"
#include "mongo/s/grid.h"
+#include "mongo/s/sharding_raii.h"
#include "mongo/s/write_ops/wc_error_detail.h"
#include "mongo/util/log.h"
@@ -81,7 +81,7 @@ bool RunOnAllShardsCommand::run(OperationContext* txn,
LOG(1) << "RunOnAllShardsCommand db: " << dbName << " cmd:" << cmdObj;
if (_implicitCreateDb) {
- uassertStatusOK(dbutil::implicitCreateDb(txn, dbName));
+ uassertStatusOK(ScopedShardDatabase::getOrCreate(txn, dbName));
}
std::vector<ShardId> shardIds;
diff --git a/src/mongo/s/db_util.cpp b/src/mongo/s/db_util.cpp
deleted file mode 100644
index ab20cccc245..00000000000
--- a/src/mongo/s/db_util.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
- * Copyright (C) 2015 MongoDB Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the GNU Affero General Public License in all respects for
- * all of the code used other than as permitted herein. If you modify file(s)
- * with this exception, you may extend this exception to your version of the
- * file(s), but you are not obligated to do so. If you do not wish to do so,
- * delete this exception statement from your version. If you delete this
- * exception statement from all source files in the program, then also delete
- * it in the license file.
- */
-
-#include "mongo/platform/basic.h"
-
-#include "mongo/s/db_util.h"
-
-#include "mongo/base/status_with.h"
-#include "mongo/s/catalog/catalog_cache.h"
-#include "mongo/s/catalog/catalog_manager.h"
-#include "mongo/s/grid.h"
-
-namespace mongo {
-namespace dbutil {
-
-StatusWith<std::shared_ptr<DBConfig>> implicitCreateDb(OperationContext* txn,
- const std::string& dbName) {
- auto status = grid.catalogCache()->getDatabase(txn, dbName);
- if (status.isOK()) {
- return status;
- }
-
- if (status == ErrorCodes::NamespaceNotFound) {
- auto statusCreateDb = grid.catalogManager(txn)->createDatabase(txn, dbName);
- if (statusCreateDb.isOK() || statusCreateDb == ErrorCodes::NamespaceExists) {
- return grid.catalogCache()->getDatabase(txn, dbName);
- }
-
- return statusCreateDb;
- }
-
- return status;
-}
-
-} // namespace dbutil
-} // namespace mongo
diff --git a/src/mongo/s/db_util.h b/src/mongo/s/db_util.h
deleted file mode 100644
index ea1104dba0a..00000000000
--- a/src/mongo/s/db_util.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/**
- * Copyright (C) 2016 MongoDB Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the GNU Affero General Public License in all respects for
- * all of the code used other than as permitted herein. If you modify file(s)
- * with this exception, you may extend this exception to your version of the
- * file(s), but you are not obligated to do so. If you do not wish to do so,
- * delete this exception statement from your version. If you delete this
- * exception statement from all source files in the program, then also delete
- * it in the license file.
- */
-
-#pragma once
-
-#include <memory>
-#include <string>
-
-namespace mongo {
-
-class DBConfig;
-class OperationContext;
-template <typename T>
-class StatusWith;
-
-namespace dbutil {
-
-/**
- * Implicitly creates the specified database as non-sharded.
- */
-StatusWith<std::shared_ptr<DBConfig>> implicitCreateDb(OperationContext* txn,
- const std::string& dbName);
-
-} // namespace dbutil
-} // namespace mongo
diff --git a/src/mongo/s/sharding_raii.cpp b/src/mongo/s/sharding_raii.cpp
new file mode 100644
index 00000000000..caacb4de8a8
--- /dev/null
+++ b/src/mongo/s/sharding_raii.cpp
@@ -0,0 +1,109 @@
+/**
+ * Copyright (C) 2016 MongoDB Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the GNU Affero General Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#include "mongo/platform/basic.h"
+
+#include "mongo/s/sharding_raii.h"
+
+#include "mongo/base/status_with.h"
+#include "mongo/s/catalog/catalog_cache.h"
+#include "mongo/s/catalog/catalog_manager.h"
+#include "mongo/s/chunk_manager.h"
+#include "mongo/s/grid.h"
+
+namespace mongo {
+
+using std::shared_ptr;
+
+ScopedShardDatabase::ScopedShardDatabase(std::shared_ptr<DBConfig> db) : _db(db) {
+ invariant(_db);
+}
+
+ScopedShardDatabase::~ScopedShardDatabase() = default;
+
+StatusWith<ScopedShardDatabase> ScopedShardDatabase::getExisting(OperationContext* txn,
+ StringData dbName) {
+ auto dbStatus = Grid::get(txn)->catalogCache()->getDatabase(txn, dbName.toString());
+ if (!dbStatus.isOK()) {
+ return {dbStatus.getStatus().code(),
+ str::stream() << "Database " << dbName << " was not found due to "
+ << dbStatus.getStatus().toString()};
+ }
+
+ return {ScopedShardDatabase(std::move(dbStatus.getValue()))};
+}
+
+StatusWith<ScopedShardDatabase> ScopedShardDatabase::getOrCreate(OperationContext* txn,
+ StringData dbName) {
+ auto dbStatus = getExisting(txn, dbName);
+ if (dbStatus.isOK()) {
+ return dbStatus;
+ }
+
+ if (dbStatus == ErrorCodes::NamespaceNotFound) {
+ auto statusCreateDb =
+ Grid::get(txn)->catalogManager(txn)->createDatabase(txn, dbName.toString());
+ if (statusCreateDb.isOK() || statusCreateDb == ErrorCodes::NamespaceExists) {
+ return getExisting(txn, dbName);
+ }
+
+ return statusCreateDb;
+ }
+
+ return dbStatus.getStatus();
+}
+
+ScopedChunkManager::ScopedChunkManager(ScopedShardDatabase db, std::shared_ptr<ChunkManager> cm)
+ : _db(std::move(db)), _cm(std::move(cm)) {}
+
+ScopedChunkManager::~ScopedChunkManager() = default;
+
+StatusWith<ScopedChunkManager> ScopedChunkManager::getExisting(OperationContext* txn,
+ const NamespaceString& nss) {
+ auto scopedDbStatus = ScopedShardDatabase::getExisting(txn, nss.db());
+ if (!scopedDbStatus.isOK()) {
+ return scopedDbStatus.getStatus();
+ }
+
+ auto scopedDb = std::move(scopedDbStatus.getValue());
+
+ shared_ptr<ChunkManager> cm = scopedDb.db()->getChunkManagerIfExists(txn, nss.ns(), true);
+ if (!cm) {
+ return {ErrorCodes::NamespaceNotSharded,
+ str::stream() << "Collection " << nss.ns() << " does not exist or is not sharded."};
+ }
+
+ if (cm->getChunkMap().empty()) {
+ return {ErrorCodes::NamespaceNotSharded,
+ str::stream() << "Collection " << nss.ns() << " does not have any chunks."};
+ }
+
+ return {ScopedChunkManager(std::move(scopedDb), std::move(cm))};
+}
+
+} // namespace mongo
diff --git a/src/mongo/s/sharding_raii.h b/src/mongo/s/sharding_raii.h
new file mode 100644
index 00000000000..a8ec79cc328
--- /dev/null
+++ b/src/mongo/s/sharding_raii.h
@@ -0,0 +1,123 @@
+/**
+ * Copyright (C) 2016 MongoDB Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the GNU Affero General Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#pragma once
+
+#include "mongo/base/disallow_copying.h"
+#include "mongo/s/chunk_manager.h"
+#include "mongo/s/config.h"
+
+namespace mongo {
+
+class DBConfig;
+class OperationContext;
+template <typename T>
+class StatusWith;
+
+class ScopedShardDatabase {
+ MONGO_DISALLOW_COPYING(ScopedShardDatabase);
+
+public:
+ ScopedShardDatabase(ScopedShardDatabase&&) = default;
+ ~ScopedShardDatabase();
+
+ /**
+ * Ensures that the specified database exists in the cache and if it does, returns it.
+ * Otherwise, either returns NamespaceNotFound if the database does not exist, or any other
+ * error code indicating why the database could not be loaded.
+ */
+ static StatusWith<ScopedShardDatabase> getExisting(OperationContext* txn, StringData dbName);
+
+ /**
+ * If the specified database exists already, loads it in the cache (if not already there) and
+ * returns it. Otherwise, if it does not exis, this call will implicitly create it as
+ * non-sharded.
+ */
+ static StatusWith<ScopedShardDatabase> getOrCreate(OperationContext* txn, StringData dbName);
+
+ /**
+ * Returns the underlying database cache entry.
+ */
+ DBConfig* db() const {
+ return _db.get();
+ }
+
+ /**
+ * This method is here only for compatibility with the legacy M/R code, which requires a shared
+ * reference to the underlying database. It should not be used in new code.
+ */
+ std::shared_ptr<DBConfig> getSharedDbReference() const {
+ return _db;
+ }
+
+private:
+ explicit ScopedShardDatabase(std::shared_ptr<DBConfig> db);
+
+ // Reference to the corresponding database. Never null.
+ std::shared_ptr<DBConfig> _db;
+};
+
+class ScopedChunkManager {
+ MONGO_DISALLOW_COPYING(ScopedChunkManager);
+
+public:
+ ScopedChunkManager(ScopedChunkManager&&) = default;
+ ~ScopedChunkManager();
+
+ /**
+ * Ensures that the specified database and collection both exist in the cache and if so, returns
+ * it. Otherwise, if it does not exist or any other error occurs, passes that error back.
+ */
+ static StatusWith<ScopedChunkManager> getExisting(OperationContext* txn,
+ const NamespaceString& nss);
+
+ /**
+ * Returns the underlying database for which we hold reference.
+ */
+ DBConfig* db() const {
+ return _db.db();
+ }
+
+ /**
+ * Returns the underlying chunk manager for which we hold reference.
+ */
+ ChunkManager* cm() const {
+ return _cm.get();
+ }
+
+private:
+ ScopedChunkManager(ScopedShardDatabase db, std::shared_ptr<ChunkManager> cm);
+
+ // Scoped reference to the owning database.
+ ScopedShardDatabase _db;
+
+ // Reference to the corresponding chunk manager. Never null.
+ std::shared_ptr<ChunkManager> _cm;
+};
+
+} // namespace mongo