diff options
-rw-r--r-- | src/mongo/s/SConscript | 2 | ||||
-rw-r--r-- | src/mongo/s/chunk.cpp | 10 | ||||
-rw-r--r-- | src/mongo/s/chunk_manager_targeter.cpp | 48 | ||||
-rw-r--r-- | src/mongo/s/commands/cluster_find_and_modify_cmd.cpp | 15 | ||||
-rw-r--r-- | src/mongo/s/commands/cluster_map_reduce_cmd.cpp | 5 | ||||
-rw-r--r-- | src/mongo/s/commands/cluster_merge_chunks_cmd.cpp | 4 | ||||
-rw-r--r-- | src/mongo/s/commands/cluster_shard_collection_cmd.cpp | 6 | ||||
-rw-r--r-- | src/mongo/s/commands/commands_public.cpp | 61 | ||||
-rw-r--r-- | src/mongo/s/commands/run_on_all_shards_cmd.cpp | 4 | ||||
-rw-r--r-- | src/mongo/s/db_util.cpp | 61 | ||||
-rw-r--r-- | src/mongo/s/db_util.h | 50 | ||||
-rw-r--r-- | src/mongo/s/sharding_raii.cpp | 109 | ||||
-rw-r--r-- | src/mongo/s/sharding_raii.h | 123 |
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 |