summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorDaniel Alabi <alabidan@gmail.com>2015-03-25 10:59:29 -0400
committerDaniel Alabi <alabidan@gmail.com>2015-03-27 08:13:17 -0400
commit18a3b8528833a478d5a207bfe5fcb8e35673ee8f (patch)
treeec717997e13491a2ddeff7d056bbc73792bc338c /src/mongo
parentef7f17be8085488ba965286fb97927a7ce3600e7 (diff)
downloadmongo-18a3b8528833a478d5a207bfe5fcb8e35673ee8f.tar.gz
SERVER-17701 Move addShard operation to the catalog manager
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/s/catalog/catalog_manager.h17
-rw-r--r--src/mongo/s/catalog/legacy/catalog_manager_legacy.cpp300
-rw-r--r--src/mongo/s/catalog/legacy/catalog_manager_legacy.h9
-rw-r--r--src/mongo/s/commands/cluster_add_shard_cmd.cpp13
-rw-r--r--src/mongo/s/grid.cpp295
-rw-r--r--src/mongo/s/grid.h15
6 files changed, 335 insertions, 314 deletions
diff --git a/src/mongo/s/catalog/catalog_manager.h b/src/mongo/s/catalog/catalog_manager.h
index 920a7b93179..1c682d70427 100644
--- a/src/mongo/s/catalog/catalog_manager.h
+++ b/src/mongo/s/catalog/catalog_manager.h
@@ -38,6 +38,7 @@ namespace mongo {
class BatchedCommandRequest;
class BatchedCommandResponse;
class BSONObj;
+ class ConnectionString;
class DatabaseType;
class OperationContext;
class Status;
@@ -69,6 +70,22 @@ namespace mongo {
virtual Status enableSharding(const std::string& dbName) = 0;
/**
+ *
+ * Adds a new shard. It expects a standalone mongod process or replica set to be running
+ * on the provided address.
+ *
+ * @param name is an optional string with the name of the shard.
+ * If empty, a name will be automatically generated.
+ * @param shardConnectionString is the connection string of the shard being added.
+ * @param maxSize is the optional space quota in bytes. Zeros means there's
+ * no limitation to space usage.
+ * @return either an !OK status or the name of the newly added shard.
+ */
+ virtual StatusWith<std::string> addShard(const std::string& name,
+ const ConnectionString& shardConnectionString,
+ const long long maxSize) = 0;
+
+ /**
* Updates the metadata for a given database. Currently, if the specified DB entry does
* not exist, it will be created.
*/
diff --git a/src/mongo/s/catalog/legacy/catalog_manager_legacy.cpp b/src/mongo/s/catalog/legacy/catalog_manager_legacy.cpp
index 7fc1733a961..76efe7c032a 100644
--- a/src/mongo/s/catalog/legacy/catalog_manager_legacy.cpp
+++ b/src/mongo/s/catalog/legacy/catalog_manager_legacy.cpp
@@ -32,11 +32,13 @@
#include "mongo/s/catalog/legacy/catalog_manager_legacy.h"
+#include <iomanip>
#include <pcrecpp.h>
#include <set>
#include <vector>
#include "mongo/client/connpool.h"
+#include "mongo/client/replica_set_monitor.h"
#include "mongo/db/client.h"
#include "mongo/db/operation_context.h"
#include "mongo/db/server_options.h"
@@ -46,6 +48,7 @@
#include "mongo/s/client/dbclient_multi_command.h"
#include "mongo/s/shard.h"
#include "mongo/s/type_database.h"
+#include "mongo/s/type_shard.h"
#include "mongo/s/write_ops/batched_command_request.h"
#include "mongo/s/write_ops/batched_command_response.h"
#include "mongo/util/mongoutils/str.h"
@@ -89,6 +92,151 @@ namespace {
dassert(response->isValid(NULL));
}
+ StatusWith<string> isValidShard(const string& name,
+ const ConnectionString& shardConnectionString,
+ ScopedDbConnection& conn) {
+ if (conn->type() == ConnectionString::SYNC) {
+ return Status(ErrorCodes::BadValue,
+ "can't use sync cluster as a shard; for a replica set, "
+ "you have to use <setname>/<server1>,<server2>,...");
+ }
+
+ BSONObj resIsMongos;
+ // (ok == 0) implies that it is a mongos
+ if (conn->runCommand("admin", BSON("isdbgrid" << 1), resIsMongos)) {
+ return Status(ErrorCodes::BadValue,
+ "can't add a mongos process as a shard");
+ }
+
+ BSONObj resIsMaster;
+ if (!conn->runCommand("admin", BSON("isMaster" << 1), resIsMaster)) {
+ return Status(ErrorCodes::OperationFailed,
+ str::stream() << "failed running isMaster: " << resIsMaster);
+ }
+
+ // if the shard has only one host, make sure it is not part of a replica set
+ string setName = resIsMaster["setName"].str();
+ string commandSetName = shardConnectionString.getSetName();
+ if (commandSetName.empty() && !setName.empty()) {
+ return Status(ErrorCodes::BadValue,
+ str::stream() << "host is part of set " << setName << "; "
+ << "use replica set url format "
+ << "<setname>/<server1>,<server2>, ...");
+ }
+
+ if (!commandSetName.empty() && setName.empty()) {
+ return Status(ErrorCodes::OperationFailed,
+ str::stream() << "host did not return a set name; "
+ << "is the replica set still initializing? "
+ << resIsMaster);
+ }
+
+ // if the shard is part of replica set, make sure it is the right one
+ if (!commandSetName.empty() && (commandSetName != setName)) {
+ return Status(ErrorCodes::OperationFailed,
+ str::stream() << "host is part of a different set: " << setName);
+ }
+
+ if (setName.empty()) {
+ // check this isn't a --configsvr
+ BSONObj res;
+ bool ok = conn->runCommand("admin",
+ BSON("replSetGetStatus" << 1),
+ res);
+ if(!ok && res["info"].type() == String && res["info"].String() == "configsvr") {
+ return Status(ErrorCodes::BadValue,
+ "the specified mongod is a --configsvr and "
+ "should thus not be a shard server");
+ }
+ }
+
+ // if the shard is part of a replica set,
+ // make sure all the hosts mentioned in 'shardConnectionString' are part of
+ // the set. It is fine if not all members of the set are present in 'shardConnectionString'.
+ bool foundAll = true;
+ string offendingHost;
+ if (!commandSetName.empty()) {
+ set<string> hostSet;
+ BSONObjIterator iter(resIsMaster["hosts"].Obj());
+ while (iter.more()) {
+ hostSet.insert(iter.next().String()); // host:port
+ }
+ if (resIsMaster["passives"].isABSONObj()) {
+ BSONObjIterator piter(resIsMaster["passives"].Obj());
+ while (piter.more()) {
+ hostSet.insert(piter.next().String()); // host:port
+ }
+ }
+ if (resIsMaster["arbiters"].isABSONObj()) {
+ BSONObjIterator piter(resIsMaster["arbiters"].Obj());
+ while (piter.more()) {
+ hostSet.insert(piter.next().String()); // host:port
+ }
+ }
+
+ vector<HostAndPort> hosts = shardConnectionString.getServers();
+ for (size_t i = 0; i < hosts.size(); i++) {
+ if (!hosts[i].hasPort()) {
+ hosts[i] = HostAndPort(hosts[i].host(), hosts[i].port());
+ }
+ string host = hosts[i].toString(); // host:port
+ if (hostSet.find(host) == hostSet.end()) {
+ offendingHost = host;
+ foundAll = false;
+ break;
+ }
+ }
+ }
+ if (!foundAll) {
+ return Status(ErrorCodes::OperationFailed,
+ str::stream() << "in seed list " << shardConnectionString.toString()
+ << ", host " << offendingHost
+ << " does not belong to replica set " << setName);
+ }
+
+ string shardName(name);
+ // shard name defaults to the name of the replica set
+ if (name.empty() && !setName.empty()) {
+ shardName = setName;
+ }
+
+ // disallow adding shard replica set with name 'config'
+ if (shardName == "config") {
+ return Status(ErrorCodes::BadValue,
+ "use of shard replica set with name 'config' is not allowed");
+ }
+
+ return shardName;
+ }
+
+ // In order to be accepted as a new shard, that mongod must not have
+ // any database name that exists already in any other shards.
+ // If that test passes, the new shard's databases are going to be entered as
+ // non-sharded db's whose primary is the newly added shard.
+ StatusWith<vector<string>> getDBNames(const ConnectionString& shardConnectionString,
+ ScopedDbConnection& conn) {
+ vector<string> dbNames;
+
+ BSONObj resListDB;
+ if (!conn->runCommand("admin", BSON("listDatabases" << 1), resListDB)) {
+ return Status(ErrorCodes::OperationFailed,
+ str::stream() << "failed listing "
+ << shardConnectionString.toString()
+ << "'s databases:" << resListDB);
+ }
+
+ BSONObjIterator i(resListDB["databases"].Obj());
+ while (i.more()) {
+ BSONObj dbEntry = i.next().Obj();
+ const string& dbName = dbEntry["name"].String();
+ if (!(dbName == "local" || dbName == "admin" || dbName == "config")) {
+ dbNames.push_back(dbName);
+ }
+ }
+
+ return dbNames;
+ }
+
// Whether the logChange call should attempt to create the changelog collection
AtomicInt32 changeLogCollectionCreated(0);
@@ -237,6 +385,129 @@ namespace {
}
}
+ StatusWith<string> CatalogManagerLegacy::addShard(const string& name,
+ const ConnectionString& shardConnectionString,
+ const long long maxSize) {
+
+ string shardName;
+ ReplicaSetMonitorPtr rsMonitor;
+ vector<string> dbNames;
+
+ try {
+ ScopedDbConnection newShardConn(shardConnectionString);
+ newShardConn->getLastError();
+
+ StatusWith<string> validShard = isValidShard(name,
+ shardConnectionString,
+ newShardConn);
+ if (!validShard.isOK()) {
+ newShardConn.done();
+ return validShard.getStatus();
+ }
+ shardName = validShard.getValue();
+
+ StatusWith<vector<string>> shardDBNames = getDBNames(shardConnectionString,
+ newShardConn);
+ if (!shardDBNames.isOK()) {
+ newShardConn.done();
+ return shardDBNames.getStatus();
+ }
+ dbNames = shardDBNames.getValue();
+
+ if (newShardConn->type() == ConnectionString::SET) {
+ rsMonitor = ReplicaSetMonitor::get(shardConnectionString.getSetName());
+ }
+
+ newShardConn.done();
+ }
+ catch (const DBException& e) {
+ if (shardConnectionString.type() == ConnectionString::SET) {
+ ReplicaSetMonitor::remove(shardConnectionString.getSetName());
+ }
+ return Status(ErrorCodes::OperationFailed,
+ str::stream() << "couldn't connect to new shard "
+ << e.what());
+ }
+
+ // check that none of the existing shard candidate's db's exist elsewhere
+ for (vector<string>::const_iterator it = dbNames.begin(); it != dbNames.end(); ++it) {
+ StatusWith<DatabaseType> dbt = getDatabase(*it);
+ if (dbt.isOK()) {
+ return Status(ErrorCodes::OperationFailed,
+ str::stream() << "can't add shard "
+ << "'" << shardConnectionString.toString() << "'"
+ << " because a local database '" << *it
+ << "' exists in another "
+ << dbt.getValue().getPrimary());
+ }
+ }
+
+ // if a name for a shard wasn't provided, pick one.
+ if (shardName.empty()) {
+ StatusWith<string> result = _getNewShardName();
+ if (!result.isOK()) {
+ return Status(ErrorCodes::OperationFailed,
+ "error generating new shard name");
+ }
+ shardName = result.getValue();
+ }
+
+ // build the ConfigDB shard document
+ BSONObjBuilder b;
+ b.append(ShardType::name(), shardName);
+ b.append(ShardType::host(),
+ rsMonitor ? rsMonitor->getServerAddress() : shardConnectionString.toString());
+ if (maxSize > 0) {
+ b.append(ShardType::maxSize(), maxSize);
+ }
+ BSONObj shardDoc = b.obj();
+
+ {
+ ScopedDbConnection conn(_configServerConnectionString, 30);
+
+ // check whether the set of hosts (or single host) is not an already a known shard
+ BSONObj old = conn->findOne(ShardType::ConfigNS,
+ BSON(ShardType::host(shardConnectionString.toString())));
+
+ if (!old.isEmpty()) {
+ conn.done();
+ return Status(ErrorCodes::OperationFailed, "host already used");
+ }
+ }
+
+ log() << "going to add shard: " << shardDoc;
+
+ Status result = insert(ShardType::ConfigNS, shardDoc, NULL);
+ if (!result.isOK()) {
+ log() << "error adding shard: " << shardDoc << " err: " << result.reason();
+ return result;
+ }
+
+ Shard::reloadShardInfo();
+
+ // add all databases of the new shard
+ for (vector<string>::const_iterator it = dbNames.begin(); it != dbNames.end(); ++it) {
+ DatabaseType dbt;
+ dbt.setName(*it);
+ dbt.setPrimary(shardName);
+ dbt.setSharded(false);
+ Status status = updateDatabase(*it, dbt);
+ if (!status.isOK()) {
+ log() << "adding shard " << shardConnectionString.toString()
+ << " even though could not add database " << *it;
+ }
+ }
+
+ // Record in changelog
+ BSONObjBuilder shardDetails;
+ shardDetails.append("name", shardName);
+ shardDetails.append("host", shardConnectionString.toString());
+
+ logChange(NULL, "addShard", "", shardDetails.obj());
+
+ return shardName;
+ }
+
Status CatalogManagerLegacy::updateDatabase(const std::string& dbName, const DatabaseType& db) {
fassert(28616, db.validate());
@@ -387,4 +658,33 @@ namespace {
return Status::OK();
}
+ StatusWith<string> CatalogManagerLegacy::_getNewShardName() const {
+ BSONObj o;
+ {
+ ScopedDbConnection conn(_configServerConnectionString, 30);
+ o = conn->findOne(ShardType::ConfigNS,
+ Query(fromjson("{" + ShardType::name() + ": /^shard/}"))
+ .sort(BSON(ShardType::name() << -1 )));
+ conn.done();
+ }
+
+ int count = 0;
+ if (!o.isEmpty()) {
+ string last = o[ShardType::name()].String();
+ std::istringstream is(last.substr(5));
+ is >> count;
+ count++;
+ }
+
+ // TODO fix so that we can have more than 10000 automatically generated shard names
+ if (count < 9999) {
+ std::stringstream ss;
+ ss << "shard" << std::setfill('0') << std::setw(4) << count;
+ return ss.str();
+ }
+
+ return Status(ErrorCodes::OperationFailed,
+ "unable to generate new shard name");
+ }
+
} // namespace mongo
diff --git a/src/mongo/s/catalog/legacy/catalog_manager_legacy.h b/src/mongo/s/catalog/legacy/catalog_manager_legacy.h
index f3bb63854c1..f017ad60111 100644
--- a/src/mongo/s/catalog/legacy/catalog_manager_legacy.h
+++ b/src/mongo/s/catalog/legacy/catalog_manager_legacy.h
@@ -52,6 +52,10 @@ namespace mongo {
virtual Status enableSharding(const std::string& dbName);
+ virtual StatusWith<std::string> addShard(const std::string& name,
+ const ConnectionString& shardConnectionString,
+ const long long maxSize);
+
virtual Status updateDatabase(const std::string& dbName, const DatabaseType& db);
virtual StatusWith<DatabaseType> getDatabase(const std::string& dbName);
@@ -71,6 +75,11 @@ namespace mongo {
*/
Status _checkDbDoesNotExist(const std::string& dbName) const;
+ /**
+ * Generates a new shard name "shard<xxxx>"
+ * where <xxxx> is an autoincrementing value and <xxxx> < 10000
+ */
+ StatusWith<std::string> _getNewShardName() const;
// Parsed config server hosts, as specified on the command line.
ConnectionString _configServerConnectionString;
diff --git a/src/mongo/s/commands/cluster_add_shard_cmd.cpp b/src/mongo/s/commands/cluster_add_shard_cmd.cpp
index e80b9e76157..6a5ceedae31 100644
--- a/src/mongo/s/commands/cluster_add_shard_cmd.cpp
+++ b/src/mongo/s/commands/cluster_add_shard_cmd.cpp
@@ -34,6 +34,7 @@
#include "mongo/db/audit.h"
#include "mongo/db/commands.h"
+#include "mongo/s/catalog/legacy/catalog_manager_legacy.h"
#include "mongo/s/grid.h"
#include "mongo/s/type_shard.h"
#include "mongo/util/log.h"
@@ -125,12 +126,16 @@ namespace {
audit::logAddShard(ClientBasic::getCurrent(), name, servers.toString(), maxSize);
- if (!grid.addShard(&name, servers, maxSize, errmsg)) {
- log() << "addshard request " << cmdObj << " failed: " << errmsg;
- return false;
+ StatusWith<string> addShardResult =
+ grid.catalogManager()->addShard(name, servers, maxSize);
+ if (!addShardResult.isOK()) {
+ log() << "addShard request '" << cmdObj << "'"
+ << " failed: " << addShardResult.getStatus().reason();
+ return appendCommandStatus(result, addShardResult.getStatus());
}
- result << "shardAdded" << name;
+ result << "shardAdded" << addShardResult.getValue();
+
return true;
}
diff --git a/src/mongo/s/grid.cpp b/src/mongo/s/grid.cpp
index a7afa6e8dc7..6d4a111640c 100644
--- a/src/mongo/s/grid.cpp
+++ b/src/mongo/s/grid.cpp
@@ -34,11 +34,9 @@
#include "mongo/s/grid.h"
-#include <iomanip>
#include <pcrecpp.h>
#include "mongo/client/connpool.h"
-#include "mongo/client/replica_set_monitor.h"
#include "mongo/db/client.h"
#include "mongo/db/json.h"
#include "mongo/db/namespace_string.h"
@@ -58,13 +56,8 @@
namespace mongo {
using std::endl;
- using std::istringstream;
using std::map;
- using std::ostringstream;
using std::set;
- using std::setfill;
- using std::setw;
- using std::stringstream;
using std::vector;
MONGO_FP_DECLARE(neverBalance);
@@ -231,261 +224,6 @@ namespace mongo {
_allowLocalShard = allow;
}
- bool Grid::addShard( string* name , const ConnectionString& servers , long long maxSize , string& errMsg ) {
- // name can be NULL, so provide a dummy one here to avoid testing it elsewhere
- string nameInternal;
- if ( ! name ) {
- name = &nameInternal;
- }
-
- ReplicaSetMonitorPtr rsMonitor;
-
- // Check whether the host (or set) exists and run several sanity checks on this request.
- // There are two set of sanity checks: making sure adding this particular shard is consistent
- // with the replica set state (if it exists) and making sure this shards databases can be
- // brought into the grid without conflict.
-
- vector<string> dbNames;
- try {
- ScopedDbConnection newShardConn(servers.toString());
- newShardConn->getLastError();
-
- if ( newShardConn->type() == ConnectionString::SYNC ) {
- newShardConn.done();
- errMsg = "can't use sync cluster as a shard. for replica set, have to use <setname>/<server1>,<server2>,...";
- return false;
- }
-
- BSONObj resIsMongos;
- bool ok = newShardConn->runCommand( "admin" , BSON( "isdbgrid" << 1 ) , resIsMongos );
-
- // should return ok=0, cmd not found if it's a normal mongod
- if ( ok ) {
- errMsg = "can't add a mongos process as a shard";
- newShardConn.done();
- return false;
- }
-
- BSONObj resIsMaster;
- ok = newShardConn->runCommand( "admin" , BSON( "isMaster" << 1 ) , resIsMaster );
- if ( !ok ) {
- ostringstream ss;
- ss << "failed running isMaster: " << resIsMaster;
- errMsg = ss.str();
- newShardConn.done();
- return false;
- }
-
- // if the shard has only one host, make sure it is not part of a replica set
- string setName = resIsMaster["setName"].str();
- string commandSetName = servers.getSetName();
- if ( commandSetName.empty() && ! setName.empty() ) {
- ostringstream ss;
- ss << "host is part of set " << setName << ", use replica set url format <setname>/<server1>,<server2>,....";
- errMsg = ss.str();
- newShardConn.done();
- return false;
- }
- if ( !commandSetName.empty() && setName.empty() ) {
- ostringstream ss;
- ss << "host did not return a set name, is the replica set still initializing? " << resIsMaster;
- errMsg = ss.str();
- newShardConn.done();
- return false;
- }
-
- // if the shard is part of replica set, make sure it is the right one
- if ( ! commandSetName.empty() && ( commandSetName != setName ) ) {
- ostringstream ss;
- ss << "host is part of a different set: " << setName;
- errMsg = ss.str();
- newShardConn.done();
- return false;
- }
-
- if( setName.empty() ) {
- // check this isn't a --configsvr
- BSONObj res;
- bool ok = newShardConn->runCommand("admin",BSON("replSetGetStatus"<<1),res);
- ostringstream ss;
- if( !ok && res["info"].type() == String && res["info"].String() == "configsvr" ) {
- errMsg = "the specified mongod is a --configsvr and should thus not be a shard server";
- newShardConn.done();
- return false;
- }
- }
-
- // if the shard is part of a replica set, make sure all the hosts mentioned in 'servers' are part of
- // the set. It is fine if not all members of the set are present in 'servers'.
- bool foundAll = true;
- string offendingHost;
- if ( ! commandSetName.empty() ) {
- set<string> hostSet;
- BSONObjIterator iter( resIsMaster["hosts"].Obj() );
- while ( iter.more() ) {
- hostSet.insert( iter.next().String() ); // host:port
- }
- if ( resIsMaster["passives"].isABSONObj() ) {
- BSONObjIterator piter( resIsMaster["passives"].Obj() );
- while ( piter.more() ) {
- hostSet.insert( piter.next().String() ); // host:port
- }
- }
- if ( resIsMaster["arbiters"].isABSONObj() ) {
- BSONObjIterator piter( resIsMaster["arbiters"].Obj() );
- while ( piter.more() ) {
- hostSet.insert( piter.next().String() ); // host:port
- }
- }
-
- vector<HostAndPort> hosts = servers.getServers();
- for ( size_t i = 0 ; i < hosts.size() ; i++ ) {
- if (!hosts[i].hasPort()) {
- hosts[i] = HostAndPort(hosts[i].host(), hosts[i].port());
- }
- string host = hosts[i].toString(); // host:port
- if ( hostSet.find( host ) == hostSet.end() ) {
- offendingHost = host;
- foundAll = false;
- break;
- }
- }
- }
- if ( ! foundAll ) {
- ostringstream ss;
- ss << "in seed list " << servers.toString() << ", host " << offendingHost
- << " does not belong to replica set " << setName;
- errMsg = ss.str();
- newShardConn.done();
- return false;
- }
-
- // shard name defaults to the name of the replica set
- if ( name->empty() && ! setName.empty() )
- *name = setName;
-
- // disallow adding shard replica set with name 'config'
- if (*name == "config") {
- errMsg = "use of shard replica set with name 'config' is not allowed";
- newShardConn.done();
- return false;
- }
-
- // In order to be accepted as a new shard, that mongod must not have any database name that exists already
- // in any other shards. If that test passes, the new shard's databases are going to be entered as
- // non-sharded db's whose primary is the newly added shard.
-
- BSONObj resListDB;
- ok = newShardConn->runCommand( "admin" , BSON( "listDatabases" << 1 ) , resListDB );
- if ( !ok ) {
- ostringstream ss;
- ss << "failed listing " << servers.toString() << "'s databases:" << resListDB;
- errMsg = ss.str();
- newShardConn.done();
- return false;
- }
-
- BSONObjIterator i( resListDB["databases"].Obj() );
- while ( i.more() ) {
- BSONObj dbEntry = i.next().Obj();
- const string& dbName = dbEntry["name"].String();
- if ( _isSpecialLocalDB( dbName ) ) {
- // 'local', 'admin', and 'config' are system DBs and should be excluded here
- continue;
- }
- else {
- dbNames.push_back( dbName );
- }
- }
-
- if ( newShardConn->type() == ConnectionString::SET )
- rsMonitor = ReplicaSetMonitor::get( setName );
-
- newShardConn.done();
- }
- catch ( DBException& e ) {
- if ( servers.type() == ConnectionString::SET ) {
- ReplicaSetMonitor::remove( servers.getSetName() );
- }
- ostringstream ss;
- ss << "couldn't connect to new shard ";
- ss << e.what();
- errMsg = ss.str();
- return false;
- }
-
- // check that none of the existing shard candidate's db's exist elsewhere
- for ( vector<string>::const_iterator it = dbNames.begin(); it != dbNames.end(); ++it ) {
- DBConfigPtr config = getDBConfig( *it , false );
- if ( config.get() != NULL ) {
- ostringstream ss;
- ss << "can't add shard " << servers.toString() << " because a local database '" << *it;
- ss << "' exists in another " << config->getPrimary().toString();
- errMsg = ss.str();
- return false;
- }
- }
-
- // if a name for a shard wasn't provided, pick one.
- if ( name->empty() && ! _getNewShardName( name ) ) {
- errMsg = "error generating new shard name";
- return false;
- }
-
- // build the ConfigDB shard document
- BSONObjBuilder b;
- b.append(ShardType::name(), *name);
- b.append(ShardType::host(),
- rsMonitor ? rsMonitor->getServerAddress() : servers.toString());
- if (maxSize > 0) {
- b.append(ShardType::maxSize(), maxSize);
- }
- BSONObj shardDoc = b.obj();
-
- {
- ScopedDbConnection conn(configServer.getPrimary().getConnString(), 30);
-
- // check whether the set of hosts (or single host) is not an already a known shard
- BSONObj old = conn->findOne(ShardType::ConfigNS,
- BSON(ShardType::host(servers.toString())));
-
- if ( ! old.isEmpty() ) {
- errMsg = "host already used";
- conn.done();
- return false;
- }
- conn.done();
- }
-
- log() << "going to add shard: " << shardDoc << endl;
-
- Status result = catalogManager()->insert(ShardType::ConfigNS, shardDoc, NULL);
- if (!result.isOK()) {
- errMsg = result.reason();
- log() << "error adding shard: " << shardDoc << " err: " << errMsg;
- return false;
- }
-
- Shard::reloadShardInfo();
-
- // add all databases of the new shard
- for ( vector<string>::const_iterator it = dbNames.begin(); it != dbNames.end(); ++it ) {
- DBConfigPtr config = getDBConfig( *it , true , *name );
- if ( ! config ) {
- log() << "adding shard " << servers << " even though could not add database " << *it << endl;
- }
- }
-
- // Record in changelog
- BSONObjBuilder shardDetails;
- shardDetails.append("name", *name);
- shardDetails.append("host", servers.toString());
-
- grid.catalogManager()->logChange(NULL, "addShard", "", shardDetails.obj());
-
- return true;
- }
-
bool Grid::knowAboutShard( const string& name ) const {
ScopedDbConnection conn(configServer.getPrimary().getConnString(), 30);
BSONObj shard = conn->findOne(ShardType::ConfigNS, BSON(ShardType::host(name)));
@@ -493,35 +231,6 @@ namespace mongo {
return ! shard.isEmpty();
}
- bool Grid::_getNewShardName(string* name) const {
- invariant(name);
-
- bool ok = false;
- int count = 0;
-
- ScopedDbConnection conn(configServer.getPrimary().getConnString(), 30);
- BSONObj o = conn->findOne(ShardType::ConfigNS,
- Query(fromjson("{" + ShardType::name() + ": /^shard/}"))
- .sort(BSON(ShardType::name() << -1 )));
- if (!o.isEmpty()) {
- string last = o[ShardType::name()].String();
- istringstream is(last.substr(5));
- is >> count;
- count++;
- }
-
- if (count < 9999) {
- stringstream ss;
- ss << "shard" << setfill('0') << setw(4) << count;
- *name = ss.str();
- ok = true;
- }
-
- conn.done();
-
- return ok;
- }
-
/*
* Returns whether balancing is enabled, with optional namespace "ns" parameter for balancing on a particular
* collection.
@@ -647,10 +356,6 @@ namespace mongo {
return false;
}
- bool Grid::_isSpecialLocalDB( const string& dbName ) {
- return ( dbName == "local" ) || ( dbName == "admin" ) || ( dbName == "config" );
- }
-
void Grid::flushConfig() {
boost::lock_guard<boost::mutex> lk( _lock );
_databases.clear();
diff --git a/src/mongo/s/grid.h b/src/mongo/s/grid.h
index cb7cb084c59..36988209572 100644
--- a/src/mongo/s/grid.h
+++ b/src/mongo/s/grid.h
@@ -98,21 +98,6 @@ namespace mongo {
void setAllowLocalHost( bool allow );
/**
- *
- * addShard will create a new shard in the grid. It expects a mongod process to be running
- * on the provided address. Adding a shard that is a replica set is supported.
- *
- * @param name is an optional std::string with the name of the shard. if omitted, grid will
- * generate one and update the parameter.
- * @param servers is the connection std::string of the shard being added
- * @param maxSize is the optional space quota in bytes. Zeros means there's no limitation to
- * space usage
- * @param errMsg is the error description in case the operation failed.
- * @return true if shard was successfully added.
- */
- bool addShard( std::string* name , const ConnectionString& servers , long long maxSize , std::string& errMsg );
-
- /**
* @return true if the config database knows about a host 'name'
*/
bool knowAboutShard( const std::string& name ) const;