diff options
author | Kaloian Manassiev <kaloian.manassiev@mongodb.com> | 2015-05-13 22:19:06 -0400 |
---|---|---|
committer | Kaloian Manassiev <kaloian.manassiev@mongodb.com> | 2015-05-14 09:55:54 -0400 |
commit | e709d899d71af93d92e817856feb15a09ca42fa3 (patch) | |
tree | 6d7af19629bb5b6124671ab7bdbab8d4d22f8e0a /src | |
parent | fed0aad352eb7f0e8f2915ad1670b579c08a6207 (diff) | |
download | mongo-e709d899d71af93d92e817856feb15a09ca42fa3.tar.gz |
SERVER-18049 Move StaticShardInfo out of shard.cpp
Renames StaticShardInfo to ShardRegistry and moves it to a separate source
file.
No functional changes, but it removes some unused code.
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/s/catalog/type_shard.cpp | 4 | ||||
-rw-r--r-- | src/mongo/s/chunk_diff-inl.h | 1 | ||||
-rw-r--r-- | src/mongo/s/chunk_diff.h | 1 | ||||
-rw-r--r-- | src/mongo/s/client/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/s/client/shard.cpp | 278 | ||||
-rw-r--r-- | src/mongo/s/client/shard.h | 35 | ||||
-rw-r--r-- | src/mongo/s/client/shard_registry.cpp | 279 | ||||
-rw-r--r-- | src/mongo/s/client/shard_registry.h | 96 | ||||
-rw-r--r-- | src/mongo/s/config.cpp | 16 | ||||
-rw-r--r-- | src/mongo/s/config.h | 9 |
10 files changed, 412 insertions, 308 deletions
diff --git a/src/mongo/s/catalog/type_shard.cpp b/src/mongo/s/catalog/type_shard.cpp index a1669cad775..7f2375ab873 100644 --- a/src/mongo/s/catalog/type_shard.cpp +++ b/src/mongo/s/catalog/type_shard.cpp @@ -115,7 +115,6 @@ namespace mongo { } Status ShardType::validate() const { - if (!_name.is_initialized() || _name->empty()) { return Status(ErrorCodes::NoSuchKey, str::stream() << "missing " << name.name() << " field"); @@ -127,8 +126,7 @@ namespace mongo { } if (_maxSize.is_initialized() && getMaxSize() < 0) { - return Status(ErrorCodes::BadValue, - str::stream() << "maxSize can't be negative"); + return Status(ErrorCodes::BadValue, str::stream() << "maxSize can't be negative"); } return Status::OK(); diff --git a/src/mongo/s/chunk_diff-inl.h b/src/mongo/s/chunk_diff-inl.h index 3ef4cc1adcd..8ace994416a 100644 --- a/src/mongo/s/chunk_diff-inl.h +++ b/src/mongo/s/chunk_diff-inl.h @@ -30,6 +30,7 @@ #pragma once +#include "mongo/client/dbclientinterface.h" #include "mongo/logger/log_severity.h" #include "mongo/logger/logger.h" #include "mongo/logger/logstream_builder.h" diff --git a/src/mongo/s/chunk_diff.h b/src/mongo/s/chunk_diff.h index 3551381cce7..0200fd68ff6 100644 --- a/src/mongo/s/chunk_diff.h +++ b/src/mongo/s/chunk_diff.h @@ -38,6 +38,7 @@ namespace mongo { class ChunkType; class CatalogManager; + class Query; /** * This class manages and applies diffs from partial config server data reloads. Because the diff --git a/src/mongo/s/client/SConscript b/src/mongo/s/client/SConscript index 0b976cc340a..725cee5d910 100644 --- a/src/mongo/s/client/SConscript +++ b/src/mongo/s/client/SConscript @@ -8,6 +8,7 @@ env.Library( 'dbclient_multi_command.cpp', 'shard.cpp', 'shard_connection.cpp', + 'shard_registry.cpp', ], LIBDEPS=[ '$BUILD_DIR/mongo/client/clientdriver', diff --git a/src/mongo/s/client/shard.cpp b/src/mongo/s/client/shard.cpp index 3f88e3e1ccd..a08a1012dad 100644 --- a/src/mongo/s/client/shard.cpp +++ b/src/mongo/s/client/shard.cpp @@ -45,264 +45,20 @@ #include "mongo/db/auth/privilege.h" #include "mongo/db/commands.h" #include "mongo/db/jsobj.h" -#include "mongo/s/catalog/catalog_manager.h" -#include "mongo/s/catalog/type_shard.h" -#include "mongo/s/grid.h" +#include "mongo/s/client/shard_registry.h" #include "mongo/util/log.h" namespace mongo { using std::list; using std::map; - using std::ostream; using std::string; using std::stringstream; using std::vector; +namespace { - class StaticShardInfo { - public: - void reload() { - - vector<ShardType> shards; - Status status = grid.catalogManager()->getAllShards(&shards); - massert(13632, "couldn't get updated shard list from config server", status.isOK()); - - int numShards = shards.size(); - - LOG(1) << "found " << numShards << " shards listed on config server(s)"; - - boost::lock_guard<boost::mutex> lk( _mutex ); - - // We use the _lookup table for all shards and for the primary config DB. The config DB info, - // however, does not come from the ShardNS::shard. So when cleaning the _lookup table we leave - // the config state intact. The rationale is that this way we could drop shards that - // were removed without reinitializing the config DB information. - - ShardMap::iterator i = _lookup.find( "config" ); - if ( i != _lookup.end() ) { - ShardPtr config = i->second; - _lookup.clear(); - _lookup[ "config" ] = config; - } - else { - _lookup.clear(); - } - _rsLookup.clear(); - - for (const ShardType& shardData : shards) { - uassertStatusOK(shardData.validate()); - - ShardPtr shard = boost::make_shared<Shard>(shardData.getName(), - shardData.getHost(), - shardData.getMaxSize(), - shardData.getDraining()); - - _lookup[shardData.getName()] = shard; - _installHost(shardData.getHost(), shard); - } - - } - - ShardPtr findUsingLookUp(const string& shardName) { - ShardMap::iterator it; - { - boost::lock_guard<boost::mutex> lk(_mutex); - it = _lookup.find(shardName); - } - if (it != _lookup.end()) return it->second; - return ShardPtr(); - } - - ShardPtr findIfExists(const string& shardName) { - ShardPtr shard = findUsingLookUp(shardName); - if (shard) { - return shard; - } - // if we can't find the shard, we might just need to reload the cache - reload(); - return findUsingLookUp(shardName); - } - - ShardPtr find(const string& ident) { - string errmsg; - ConnectionString connStr = ConnectionString::parse(ident, errmsg); - - uassert(18642, str::stream() << "Error parsing connection string: " << ident, - errmsg.empty()); - - if (connStr.type() == ConnectionString::SET) { - boost::lock_guard<boost::mutex> lk(_rsMutex); - ShardMap::iterator iter = _rsLookup.find(connStr.getSetName()); - - if (iter == _rsLookup.end()) { - return ShardPtr(); - } - - return iter->second; - } - else { - boost::lock_guard<boost::mutex> lk(_mutex); - ShardMap::iterator iter = _lookup.find(ident); - - if (iter == _lookup.end()) { - return ShardPtr(); - } - - return iter->second; - } - } - - ShardPtr findWithRetry(const string& ident) { - ShardPtr shard(find(ident)); - - if (shard != NULL) { - return shard; - } - - // not in our maps, re-load all - reload(); - - shard = find(ident); - massert(13129 , str::stream() << "can't find shard for: " << ident, shard != NULL); - return shard; - } - - // Lookup shard by replica set name. Returns Shard::EMTPY if the name can't be found. - // Note: this doesn't refresh the table if the name isn't found, so it's possible that - // a newly added shard/Replica Set may not be found. - Shard lookupRSName( const string& name) { - boost::lock_guard<boost::mutex> lk( _rsMutex ); - ShardMap::iterator i = _rsLookup.find( name ); - - return (i == _rsLookup.end()) ? Shard::EMPTY : *(i->second.get()); - } - - // Useful for ensuring our shard data will not be modified while we use it - Shard findCopy( const string& ident ){ - ShardPtr found = findWithRetry(ident); - boost::lock_guard<boost::mutex> lk( _mutex ); - massert( 13128 , (string)"can't find shard for: " + ident , found.get() ); - return *found.get(); - } - - void set( const string& name , const Shard& s , bool setName = true , bool setAddr = true ) { - boost::lock_guard<boost::mutex> lk( _mutex ); - ShardPtr ss( new Shard( s ) ); - if ( setName ) - _lookup[name] = ss; - if ( setAddr ) - _installHost( s.getConnString() , ss ); - } - - void _installHost( const string& host , const ShardPtr& s ) { - _lookup[host] = s; - - const ConnectionString& cs = s->getAddress(); - if ( cs.type() == ConnectionString::SET ) { - if ( cs.getSetName().size() ) { - boost::lock_guard<boost::mutex> lk( _rsMutex); - _rsLookup[ cs.getSetName() ] = s; - } - vector<HostAndPort> servers = cs.getServers(); - for ( unsigned i=0; i<servers.size(); i++ ) { - _lookup[ servers[i].toString() ] = s; - } - } - } - - void remove( const string& name ) { - boost::lock_guard<boost::mutex> lk( _mutex ); - for ( ShardMap::iterator i = _lookup.begin(); i!=_lookup.end(); ) { - ShardPtr s = i->second; - if ( s->getName() == name ) { - _lookup.erase(i++); - } - else { - ++i; - } - } - for ( ShardMap::iterator i = _rsLookup.begin(); i!=_rsLookup.end(); ) { - ShardPtr s = i->second; - if ( s->getName() == name ) { - _rsLookup.erase(i++); - } - else { - ++i; - } - } - } - - void getAllShards( vector<ShardPtr>& all ) const { - boost::lock_guard<boost::mutex> lk( _mutex ); - std::set<string> seen; - for ( ShardMap::const_iterator i = _lookup.begin(); i!=_lookup.end(); ++i ) { - const ShardPtr& s = i->second; - if ( s->getName() == "config" ) - continue; - if ( seen.count( s->getName() ) ) - continue; - seen.insert( s->getName() ); - all.push_back( s ); - } - } - - void getAllShards( vector<Shard>& all ) const { - boost::lock_guard<boost::mutex> lk( _mutex ); - std::set<string> seen; - for ( ShardMap::const_iterator i = _lookup.begin(); i!=_lookup.end(); ++i ) { - const ShardPtr& s = i->second; - if ( s->getName() == "config" ) - continue; - if ( seen.count( s->getName() ) ) - continue; - seen.insert( s->getName() ); - all.push_back( *s ); - } - } - - - bool isAShardNode( const string& addr ) const { - boost::lock_guard<boost::mutex> lk( _mutex ); - - // check direct nods or set names - ShardMap::const_iterator i = _lookup.find( addr ); - if ( i != _lookup.end() ) - return true; - - // check for set nodes - for ( ShardMap::const_iterator i = _lookup.begin(); i!=_lookup.end(); ++i ) { - if ( i->first == "config" ) - continue; - - if ( i->second->containsNode( addr ) ) - return true; - } - - return false; - } - - bool getShardMap( BSONObjBuilder& result , string& errmsg ) const { - boost::lock_guard<boost::mutex> lk( _mutex ); - - BSONObjBuilder b( _lookup.size() + 50 ); - - for ( ShardMap::const_iterator i = _lookup.begin(); i!=_lookup.end(); ++i ) { - b.append( i->first , i->second->getConnString() ); - } - - result.append( "map" , b.obj() ); - - return true; - } - - private: - typedef map<string,ShardPtr> ShardMap; - ShardMap _lookup; // Map of both shardName -> Shard and hostName -> Shard - ShardMap _rsLookup; // Map from ReplSet name to shard - mutable mongo::mutex _mutex; - mutable mongo::mutex _rsMutex; - } staticShardInfo; + ShardRegistry staticShardInfo; class CmdGetShardMap : public Command { @@ -319,16 +75,24 @@ namespace mongo { actions.addAction(ActionType::getShardMap); out->push_back(Privilege(ResourcePattern::forClusterResource(), actions)); } + virtual bool run(OperationContext* txn, const string&, mongo::BSONObj&, int, std::string& errmsg , mongo::BSONObjBuilder& result) { - return staticShardInfo.getShardMap( result , errmsg ); + + staticShardInfo.toBSON(&result); + + return true; } + } cmdGetShardMap; +} // namespace + + Shard::Shard() : _name(""), _addr(""), @@ -408,12 +172,8 @@ namespace mongo { return staticShardInfo.lookupRSName(name); } - void Shard::printShardInfo( ostream& out ) { - vector<Shard> all; - staticShardInfo.getAllShards( all ); - for ( unsigned i=0; i<all.size(); i++ ) - out << all[i].toString() << "\n"; - out.flush(); + BSONObj Shard::runCommand(const std::string& db, const std::string& simple) const { + return runCommand(db, BSON(simple << 1)); } BSONObj Shard::runCommand( const string& db , const BSONObj& cmd ) const { @@ -428,9 +188,11 @@ namespace mongo { return res; } - bool Shard::runCommand(const string& db, - const BSONObj& cmd, - BSONObj& res) const { + bool Shard::runCommand(const std::string& db, const std::string& simple, BSONObj& res) const { + return runCommand(db, BSON(simple << 1), res); + } + + bool Shard::runCommand(const string& db, const BSONObj& cmd, BSONObj& res) const { ScopedDbConnection conn(getConnString()); bool ok = conn->runCommand(db, cmd, res); conn.done(); @@ -515,7 +277,7 @@ namespace mongo { } void Shard::installShard(const std::string& name, const Shard& shard) { - staticShardInfo.set(name, shard, true, false); + staticShardInfo.set(name, shard); } ShardStatus::ShardStatus(const Shard& shard, long long dataSizeBytes, const string& version): diff --git a/src/mongo/s/client/shard.h b/src/mongo/s/client/shard.h index 78e73a6ac36..72df5387852 100644 --- a/src/mongo/s/client/shard.h +++ b/src/mongo/s/client/shard.h @@ -30,7 +30,7 @@ #include <boost/shared_ptr.hpp> -#include "mongo/client/dbclientinterface.h" +#include "mongo/client/connection_string.h" namespace mongo { @@ -126,25 +126,11 @@ namespace mongo { bool ok() const { return _addr.size() > 0; } - // Set internal to true to run the command with internal authentication privileges. - BSONObj runCommand( const std::string& db , const std::string& simple ) const { - return runCommand( db , BSON( simple << 1 ) ); - } - BSONObj runCommand( const std::string& db , const BSONObj& cmd ) const ; - - /** - * Runs a command on this shard. This method signature matches that of - * the connection on which this method relies upon. - */ - bool runCommand(const std::string& db, - const BSONObj& cmd, - BSONObj& res) const; + BSONObj runCommand(const std::string& db, const std::string& simple) const; + BSONObj runCommand(const std::string& db, const BSONObj& cmd) const; - bool runCommand(const std::string& db, - const std::string& simple, - BSONObj& res) const { - return runCommand(db, BSON(simple << 1), res); - } + bool runCommand(const std::string& db, const std::string& simple, BSONObj& res) const; + bool runCommand(const std::string& db, const BSONObj& cmd, BSONObj& res) const; /** * Returns the version string from the shard based from the serverStatus command result. @@ -163,13 +149,12 @@ namespace mongo { /** * mostly for replica set - * retursn true if node is the shard + * retursn true if node is the shard * of if the replica set contains node */ bool containsNode( const std::string& node ) const; static void getAllShards( std::vector<Shard>& all ); - static void printShardInfo( std::ostream& out ); static Shard lookupRSName( const std::string& name); /** @@ -203,17 +188,11 @@ namespace mongo { class ShardStatus { public: - ShardStatus(const Shard& shard, long long dataSizeBytes, const std::string& version); - friend std::ostream& operator << (std::ostream& out, const ShardStatus& s) { - out << s.toString(); - return out; - } - std::string toString() const { std::stringstream ss; - ss << "shard: " << _shard + ss << "shard: " << _shard.toString() << " dataSizeBytes: " << _dataSizeBytes << " version: " << _mongoVersion; return ss.str(); diff --git a/src/mongo/s/client/shard_registry.cpp b/src/mongo/s/client/shard_registry.cpp new file mode 100644 index 00000000000..9b31c60d101 --- /dev/null +++ b/src/mongo/s/client/shard_registry.cpp @@ -0,0 +1,279 @@ +/** + * 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. + */ + +#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kSharding + +#include "mongo/platform/basic.h" + +#include "mongo/s/client/shard_registry.h" + +#include <boost/make_shared.hpp> +#include <boost/thread/lock_guard.hpp> + +#include "mongo/client/connection_string.h" +#include "mongo/s/catalog/catalog_manager.h" +#include "mongo/s/catalog/type_shard.h" +#include "mongo/s/client/shard.h" +#include "mongo/s/grid.h" +#include "mongo/util/log.h" +#include "mongo/util/mongoutils/str.h" + +namespace mongo { + + using boost::shared_ptr; + using std::string; + using std::vector; + + + ShardRegistry::ShardRegistry() = default; + + ShardRegistry::~ShardRegistry() = default; + + void ShardRegistry::reload() { + vector<ShardType> shards; + Status status = grid.catalogManager()->getAllShards(&shards); + massert(13632, "couldn't get updated shard list from config server", status.isOK()); + + int numShards = shards.size(); + + LOG(1) << "found " << numShards << " shards listed on config server(s)"; + + boost::lock_guard<boost::mutex> lk(_mutex); + + // We use the _lookup table for all shards and for the primary config DB. The config DB + // info, however, does not come from the ShardNS::shard. So when cleaning the _lookup table + // we leave the config state intact. The rationale is that this way we could drop shards + // that were removed without reinitializing the config DB information. + + ShardMap::iterator i = _lookup.find("config"); + if (i != _lookup.end()) { + shared_ptr<Shard> config = i->second; + _lookup.clear(); + _lookup["config"] = config; + } + else { + _lookup.clear(); + } + + _rsLookup.clear(); + + for (const ShardType& shardData : shards) { + uassertStatusOK(shardData.validate()); + + shared_ptr<Shard> shard = boost::make_shared<Shard>(shardData.getName(), + shardData.getHost(), + shardData.getMaxSize(), + shardData.getDraining()); + _lookup[shardData.getName()] = shard; + _lookup[shardData.getHost()] = shard; + + const ConnectionString& cs = shard->getAddress(); + + if (cs.type() == ConnectionString::SET) { + if (cs.getSetName().size()) { + boost::lock_guard<boost::mutex> lk(_rsMutex); + _rsLookup[cs.getSetName()] = shard; + } + + vector<HostAndPort> servers = cs.getServers(); + for (unsigned i = 0; i < servers.size(); i++) { + _lookup[servers[i].toString()] = shard; + } + } + } + } + + shared_ptr<Shard> ShardRegistry::findIfExists(const string& shardName) { + shared_ptr<Shard> shard = _findUsingLookUp(shardName); + if (shard) { + return shard; + } + + // If we can't find the shard, we might just need to reload the cache + reload(); + + return _findUsingLookUp(shardName); + } + + shared_ptr<Shard> ShardRegistry::find(const string& ident) { + string errmsg; + ConnectionString connStr = ConnectionString::parse(ident, errmsg); + uassert(18642, + str::stream() << "Error parsing connection string: " << ident, + errmsg.empty()); + + if (connStr.type() == ConnectionString::SET) { + boost::lock_guard<boost::mutex> lk(_rsMutex); + ShardMap::iterator iter = _rsLookup.find(connStr.getSetName()); + + if (iter == _rsLookup.end()) { + return nullptr; + } + + return iter->second; + } + else { + boost::lock_guard<boost::mutex> lk(_mutex); + ShardMap::iterator iter = _lookup.find(ident); + + if (iter == _lookup.end()) { + return nullptr; + } + + return iter->second; + } + } + + Shard ShardRegistry::lookupRSName(const string& name) { + boost::lock_guard<boost::mutex> lk(_rsMutex); + ShardMap::iterator i = _rsLookup.find(name); + + return (i == _rsLookup.end()) ? Shard::EMPTY : *(i->second.get()); + } + + Shard ShardRegistry::findCopy(const string& ident){ + shared_ptr<Shard> found = _findWithRetry(ident); + + boost::lock_guard<boost::mutex> lk(_mutex); + massert(13128, str::stream() << "can't find shard for: " << ident, found.get()); + + return *found.get(); + } + + void ShardRegistry::set(const string& name, const Shard& s) { + shared_ptr<Shard> ss(boost::make_shared<Shard>(s)); + + boost::lock_guard<boost::mutex> lk(_mutex); + _lookup[name] = ss; + } + + void ShardRegistry::remove(const string& name) { + boost::lock_guard<boost::mutex> lk(_mutex); + + for (ShardMap::iterator i = _lookup.begin(); i != _lookup.end();) { + shared_ptr<Shard> s = i->second; + if (s->getName() == name) { + _lookup.erase(i++); + } + else { + ++i; + } + } + + for (ShardMap::iterator i = _rsLookup.begin(); i != _rsLookup.end();) { + shared_ptr<Shard> s = i->second; + if (s->getName() == name) { + _rsLookup.erase(i++); + } + else { + ++i; + } + } + } + + void ShardRegistry::getAllShards(vector<Shard>& all) const { + std::set<string> seen; + + boost::lock_guard<boost::mutex> lk(_mutex); + for (ShardMap::const_iterator i = _lookup.begin(); i != _lookup.end(); ++i) { + const shared_ptr<Shard>& s = i->second; + if (s->getName() == "config") { + continue; + } + + if (seen.count(s->getName())) { + continue; + } + + seen.insert(s->getName()); + all.push_back(*s); + } + } + + bool ShardRegistry::isAShardNode(const string& addr) const { + boost::lock_guard<boost::mutex> lk(_mutex); + + // Check direct nods or set names + ShardMap::const_iterator i = _lookup.find(addr); + if (i != _lookup.end()) { + return true; + } + + // Check for set nodes + for (ShardMap::const_iterator i = _lookup.begin(); i != _lookup.end(); ++i) { + if (i->first == "config") { + continue; + } + + if (i->second->containsNode(addr)) { + return true; + } + } + + return false; + } + + void ShardRegistry::toBSON(BSONObjBuilder* result) const { + BSONObjBuilder b(_lookup.size() + 50); + + boost::lock_guard<boost::mutex> lk(_mutex); + + for (ShardMap::const_iterator i = _lookup.begin(); i != _lookup.end(); ++i) { + b.append(i->first, i->second->getConnString()); + } + + result->append("map", b.obj()); + } + + shared_ptr<Shard> ShardRegistry::_findWithRetry(const string& ident) { + shared_ptr<Shard> shard(find(ident)); + if (shard != nullptr) { + return shard; + } + + // Not in our maps, re-load all + reload(); + + shard = find(ident); + massert(13129, str::stream() << "can't find shard for: " << ident, shard != NULL); + + return shard; + } + + shared_ptr<Shard> ShardRegistry::_findUsingLookUp(const string& shardName) { + boost::lock_guard<boost::mutex> lk(_mutex); + ShardMap::iterator it = _lookup.find(shardName); + + if (it != _lookup.end()) { + return it->second; + } + + return nullptr; + } + +} // namespace mongo diff --git a/src/mongo/s/client/shard_registry.h b/src/mongo/s/client/shard_registry.h new file mode 100644 index 00000000000..6320652b634 --- /dev/null +++ b/src/mongo/s/client/shard_registry.h @@ -0,0 +1,96 @@ +/** + * 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. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> +#include <boost/thread/mutex.hpp> +#include <string> +#include <vector> + +namespace mongo { + + class BSONObjBuilder; + class Shard; + + + /** + * Maintains the set of all shards known to the MongoS instance. + */ + class ShardRegistry { + public: + ShardRegistry(); + ~ShardRegistry(); + + void reload(); + + boost::shared_ptr<Shard> findIfExists(const std::string& shardName); + boost::shared_ptr<Shard> find(const std::string& ident); + + /** + * Lookup shard by replica set name. Returns Shard::EMTPY if the name can't be found. + * Note: this doesn't refresh the table if the name isn't found, so it's possible that a + * newly added shard/Replica Set may not be found. + */ + Shard lookupRSName(const std::string& name); + + /** + * Useful for ensuring our shard data will not be modified while we use it. + */ + Shard findCopy(const std::string& ident); + + void set(const std::string& name, const Shard& s); + + void remove(const std::string& name); + + void getAllShards(std::vector<Shard>& all) const; + + bool isAShardNode(const std::string& addr) const; + + void toBSON(BSONObjBuilder* result) const; + + + private: + typedef std::map<std::string, boost::shared_ptr<Shard>> ShardMap; + + + boost::shared_ptr<Shard> _findWithRetry(const std::string& ident); + + boost::shared_ptr<Shard> _findUsingLookUp(const std::string& shardName); + + + // Map of both shardName -> Shard and hostName -> Shard + mutable boost::mutex _mutex; + ShardMap _lookup; + + // Map from ReplSet name to shard + mutable boost::mutex _rsMutex; + ShardMap _rsLookup; + }; + +} // namespace mongo diff --git a/src/mongo/s/config.cpp b/src/mongo/s/config.cpp index 4e419bf39e6..a7fde93c451 100644 --- a/src/mongo/s/config.cpp +++ b/src/mongo/s/config.cpp @@ -180,18 +180,6 @@ namespace mongo { return i->second.isSharded(); } - ShardPtr DBConfig::getShardIfExists( const string& ns ){ - try{ - // TODO: this function assumes the _primary will not change under-the-covers, but so does - // getShard() in general - return ShardPtr( new Shard( getShard( ns ) ) ); - } - catch( AssertionException& e ){ - warning() << "primary not found for " << ns << causedBy( e ) << endl; - return ShardPtr(); - } - } - const Shard& DBConfig::getShard( const string& ns ) { if ( isSharded( ns ) ) return Shard::EMPTY; @@ -240,7 +228,9 @@ namespace mongo { } // Handles weird logic related to getting *either* a chunk manager *or* the collection primary shard - void DBConfig::getChunkManagerOrPrimary( const string& ns, ChunkManagerPtr& manager, ShardPtr& primary ){ + void DBConfig::getChunkManagerOrPrimary(const string& ns, + boost::shared_ptr<ChunkManager>& manager, + boost::shared_ptr<Shard>& primary) { // The logic here is basically that at any time, our collection can become sharded or unsharded // via a command. If we're not sharded, we want to send data to the primary, if sharded, we want diff --git a/src/mongo/s/config.h b/src/mongo/s/config.h index 1bbb1d2dd41..3be7bc1bba7 100644 --- a/src/mongo/s/config.h +++ b/src/mongo/s/config.h @@ -125,17 +125,14 @@ namespace mongo { // Atomically returns *either* the chunk manager *or* the primary shard for the collection, // neither if the collection doesn't exist. - void getChunkManagerOrPrimary(const std::string& ns, boost::shared_ptr<ChunkManager>& manager, ShardPtr& primary); + void getChunkManagerOrPrimary(const std::string& ns, + boost::shared_ptr<ChunkManager>& manager, + boost::shared_ptr<Shard>& primary); boost::shared_ptr<ChunkManager> getChunkManager(const std::string& ns, bool reload = false, bool forceReload = false); boost::shared_ptr<ChunkManager> getChunkManagerIfExists(const std::string& ns, bool reload = false, bool forceReload = false); const Shard& getShard( const std::string& ns ); - /** - * @return the correct for shard for the ns - * if the namespace is sharded, will return NULL - */ - ShardPtr getShardIfExists( const std::string& ns ); void setPrimary( const std::string& s ); |