summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mongo/s/chunk_diff-inl.h1
-rw-r--r--src/mongo/s/chunk_diff.h1
-rw-r--r--src/mongo/s/client/SConscript1
-rw-r--r--src/mongo/s/client/shard.cpp278
-rw-r--r--src/mongo/s/client/shard.h35
-rw-r--r--src/mongo/s/client/shard_registry.cpp284
-rw-r--r--src/mongo/s/client/shard_registry.h98
-rw-r--r--src/mongo/s/config.cpp16
-rw-r--r--src/mongo/s/config.h9
9 files changed, 418 insertions, 305 deletions
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..31a34039345
--- /dev/null
+++ b/src/mongo/s/client/shard_registry.cpp
@@ -0,0 +1,284 @@
+/**
+ * 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;
+ _installHost(shardData.getHost(), 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 boost::make_shared<Shard>();
+ }
+
+ return iter->second;
+ }
+ else {
+ boost::lock_guard<boost::mutex> lk(_mutex);
+ ShardMap::iterator iter = _lookup.find(ident);
+
+ if (iter == _lookup.end()) {
+ return boost::make_shared<Shard>();
+ }
+
+ 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 != 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;
+ }
+
+
+ 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 boost::make_shared<Shard>();
+ }
+
+ void ShardRegistry::_installHost(const string& host, const shared_ptr<Shard>& 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;
+ }
+ }
+ }
+
+} // 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..b888d55e723
--- /dev/null
+++ b/src/mongo/s/client/shard_registry.h
@@ -0,0 +1,98 @@
+/**
+ * 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);
+
+ void _installHost(const std::string& host, const boost::shared_ptr<Shard>& s);
+
+
+ // 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 1ea84e8c9be..f7bdc8fbb5c 100644
--- a/src/mongo/s/config.cpp
+++ b/src/mongo/s/config.cpp
@@ -178,18 +178,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;
@@ -238,7 +226,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 );