@@ -124,27 +124,13 @@ void toBatchError(const Status& status, BatchedCommandResponse* response) {
124124 response->setOk (false );
125125}
126126
127- /* *
128- * Validates that the specified connection string can serve as a shard server. In particular,
129- * this function checks that the shard can be contacted, that it is not already member of
130- * another sharded cluster and etc.
131- *
132- * @param shardRegistry Shard registry to use for opening connections to the shards.
133- * @param connectionString Connection string to be attempted as a shard host.
134- * @param shardProposedName Optional proposed name for the shard. Can be omitted in which case
135- * a unique name for the shard will be generated from the shard's connection string. If it
136- * is not omitted, the value cannot be the empty string.
137- *
138- * On success returns a partially initialized shard type object corresponding to the requested
139- * shard. It will have the hostName field set and optionally the name, if the name could be
140- * generated from either the proposed name or the connection string set name. The returned
141- * shard's name should be checked and if empty, one should be generated using some uniform
142- * algorithm.
143- */
144- StatusWith<ShardType> validateHostAsShard (OperationContext* txn,
145- ShardRegistry* shardRegistry,
146- const ConnectionString& connectionString,
147- const std::string* shardProposedName) {
127+ } // namespace
128+
129+ StatusWith<ShardType> CatalogManagerReplicaSet::_validateHostAsShard (
130+ OperationContext* txn,
131+ ShardRegistry* shardRegistry,
132+ const ConnectionString& connectionString,
133+ const std::string* shardProposedName) {
148134 if (connectionString.type () == ConnectionString::INVALID) {
149135 return {ErrorCodes::BadValue, " Invalid connection string" };
150136 }
@@ -153,14 +139,13 @@ StatusWith<ShardType> validateHostAsShard(OperationContext* txn,
153139 return {ErrorCodes::BadValue, " shard name cannot be empty" };
154140 }
155141
142+ // TODO: Don't create a detached Shard object, create a detached RemoteCommandTargeter instead.
156143 const std::shared_ptr<Shard> shardConn{shardRegistry->createConnection (connectionString)};
157144 invariant (shardConn);
158-
159- const ReadPreferenceSetting readPref{ReadPreference::PrimaryOnly};
145+ auto targeter = shardConn->getTargeter ();
160146
161147 // Is it mongos?
162- auto cmdStatus = shardRegistry->runIdempotentCommandForAddShard (
163- txn, shardConn, readPref, " admin" , BSON (" isdbgrid" << 1 ));
148+ auto cmdStatus = _runCommandForAddShard (txn, targeter.get (), " admin" , BSON (" isdbgrid" << 1 ));
164149 if (!cmdStatus.isOK ()) {
165150 return cmdStatus.getStatus ();
166151 }
@@ -171,8 +156,7 @@ StatusWith<ShardType> validateHostAsShard(OperationContext* txn,
171156 }
172157
173158 // Is it a replica set?
174- cmdStatus = shardRegistry->runIdempotentCommandForAddShard (
175- txn, shardConn, readPref, " admin" , BSON (" isMaster" << 1 ));
159+ cmdStatus = _runCommandForAddShard (txn, targeter.get (), " admin" , BSON (" isMaster" << 1 ));
176160 if (!cmdStatus.isOK ()) {
177161 return cmdStatus.getStatus ();
178162 }
@@ -205,8 +189,7 @@ StatusWith<ShardType> validateHostAsShard(OperationContext* txn,
205189 }
206190
207191 // Is it a mongos config server?
208- cmdStatus = shardRegistry->runIdempotentCommandForAddShard (
209- txn, shardConn, readPref, " admin" , BSON (" replSetGetStatus" << 1 ));
192+ cmdStatus = _runCommandForAddShard (txn, targeter.get (), " admin" , BSON (" replSetGetStatus" << 1 ));
210193 if (!cmdStatus.isOK ()) {
211194 return cmdStatus.getStatus ();
212195 }
@@ -298,22 +281,15 @@ StatusWith<ShardType> validateHostAsShard(OperationContext* txn,
298281 return shard;
299282}
300283
301- /* *
302- * Runs the listDatabases command on the specified host and returns the names of all databases
303- * it returns excluding those named local and admin, since they serve administrative purpose.
304- */
305- StatusWith<std::vector<std::string>> getDBNamesListFromShard (
284+ StatusWith<std::vector<std::string>> CatalogManagerReplicaSet::_getDBNamesListFromShard (
306285 OperationContext* txn, ShardRegistry* shardRegistry, const ConnectionString& connectionString) {
286+ // TODO: Don't create a detached Shard object, create a detached RemoteCommandTargeter instead.
307287 const std::shared_ptr<Shard> shardConn{
308288 shardRegistry->createConnection (connectionString).release ()};
309289 invariant (shardConn);
310290
311- auto cmdStatus = shardRegistry->runIdempotentCommandForAddShard (
312- txn,
313- shardConn,
314- ReadPreferenceSetting{ReadPreference::PrimaryOnly},
315- " admin" ,
316- BSON (" listDatabases" << 1 ));
291+ auto cmdStatus = _runCommandForAddShard (
292+ txn, shardConn->getTargeter ().get (), " admin" , BSON (" listDatabases" << 1 ));
317293 if (!cmdStatus.isOK ()) {
318294 return cmdStatus.getStatus ();
319295 }
@@ -338,15 +314,22 @@ StatusWith<std::vector<std::string>> getDBNamesListFromShard(
338314 return dbNames;
339315}
340316
341- } // namespace
342-
343- CatalogManagerReplicaSet::CatalogManagerReplicaSet (std::unique_ptr<DistLockManager> distLockManager)
344- : _distLockManager(std::move(distLockManager)) {}
317+ CatalogManagerReplicaSet::CatalogManagerReplicaSet (
318+ std::unique_ptr<DistLockManager> distLockManager,
319+ std::unique_ptr<executor::TaskExecutor> addShardExecutor)
320+ : _distLockManager(std::move(distLockManager)),
321+ _executorForAddShard(std::move(addShardExecutor)) {}
345322
346323CatalogManagerReplicaSet::~CatalogManagerReplicaSet () = default ;
347324
348325Status CatalogManagerReplicaSet::startup (OperationContext* txn) {
326+ stdx::lock_guard<stdx::mutex> lk (_mutex);
327+ if (_started) {
328+ return Status::OK ();
329+ }
330+ _started = true ;
349331 _distLockManager->startUp ();
332+ _executorForAddShard->startup ();
350333 return Status::OK ();
351334}
352335
@@ -359,6 +342,43 @@ void CatalogManagerReplicaSet::shutDown(OperationContext* txn) {
359342
360343 invariant (_distLockManager);
361344 _distLockManager->shutDown (txn);
345+ _executorForAddShard->shutdown ();
346+ _executorForAddShard->join ();
347+ }
348+
349+ StatusWith<BSONObj> CatalogManagerReplicaSet::_runCommandForAddShard (
350+ OperationContext* txn,
351+ RemoteCommandTargeter* targeter,
352+ const std::string& dbName,
353+ const BSONObj& cmdObj) {
354+ auto host = targeter->findHost (ReadPreferenceSetting{ReadPreference::PrimaryOnly},
355+ RemoteCommandTargeter::selectFindHostMaxWaitTime (txn));
356+ if (!host.isOK ()) {
357+ return host.getStatus ();
358+ }
359+
360+ executor::RemoteCommandRequest request (
361+ host.getValue (), dbName, cmdObj, rpc::makeEmptyMetadata (), Seconds (30 ));
362+ StatusWith<executor::RemoteCommandResponse> responseStatus =
363+ Status (ErrorCodes::InternalError, " Internal error running command" );
364+
365+ auto callStatus = _executorForAddShard->scheduleRemoteCommand (
366+ request,
367+ [&responseStatus](const executor::TaskExecutor::RemoteCommandCallbackArgs& args) {
368+ responseStatus = args.response ;
369+ });
370+ if (!callStatus.isOK ()) {
371+ return callStatus.getStatus ();
372+ }
373+
374+ // Block until the command is carried out
375+ _executorForAddShard->wait (callStatus.getValue ());
376+
377+ if (!responseStatus.isOK ()) {
378+ return responseStatus.getStatus ();
379+ }
380+
381+ return responseStatus.getValue ().data .getOwned ();
362382}
363383
364384StatusWith<string> CatalogManagerReplicaSet::addShard (OperationContext* txn,
@@ -367,7 +387,7 @@ StatusWith<string> CatalogManagerReplicaSet::addShard(OperationContext* txn,
367387 const long long maxSize) {
368388 // Validate the specified connection string may serve as shard at all
369389 auto shardStatus =
370- validateHostAsShard (txn, grid.shardRegistry (), shardConnectionString, shardProposedName);
390+ _validateHostAsShard (txn, grid.shardRegistry (), shardConnectionString, shardProposedName);
371391 if (!shardStatus.isOK ()) {
372392 // TODO: This is a workaround for the case were we could have some bad shard being
373393 // requested to be added and we put that bad connection string on the global replica set
@@ -379,7 +399,7 @@ StatusWith<string> CatalogManagerReplicaSet::addShard(OperationContext* txn,
379399
380400 ShardType& shardType = shardStatus.getValue ();
381401
382- auto dbNamesStatus = getDBNamesListFromShard (txn, grid.shardRegistry (), shardConnectionString);
402+ auto dbNamesStatus = _getDBNamesListFromShard (txn, grid.shardRegistry (), shardConnectionString);
383403 if (!dbNamesStatus.isOK ()) {
384404 return dbNamesStatus.getStatus ();
385405 }
@@ -1969,4 +1989,8 @@ Status CatalogManagerReplicaSet::appendInfoForConfigServerDatabases(OperationCon
19691989 return Status::OK ();
19701990}
19711991
1992+ void CatalogManagerReplicaSet::appendConnectionStats (executor::ConnectionPoolStats* stats) {
1993+ _executorForAddShard->appendConnectionStats (stats);
1994+ }
1995+
19721996} // namespace mongo
0 commit comments