summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKaloian Manassiev <kaloian.manassiev@mongodb.com>2015-03-11 10:38:01 -0400
committerKaloian Manassiev <kaloian.manassiev@mongodb.com>2015-03-11 16:30:45 -0400
commit73986ce87913a552858cfd4c187a0f1059324a03 (patch)
tree5e8437e401115bb043db7098c7e63bec5a290aea /src
parent5fd3dfce18655932165ebadef0bbe5ed58f678de (diff)
downloadmongo-73986ce87913a552858cfd4c187a0f1059324a03.tar.gz
SERVER-17496 Move all admin commands to separate files
Diffstat (limited to 'src')
-rw-r--r--src/mongo/SConscript1
-rw-r--r--src/mongo/s/commands/SConscript13
-rw-r--r--src/mongo/s/commands/cluster_add_shard_cmd.cpp141
-rw-r--r--src/mongo/s/commands/cluster_get_prev_error_cmd.cpp80
-rw-r--r--src/mongo/s/commands/cluster_get_shard_version_cmd.cpp (renamed from src/mongo/s/commands/cluster_get_shard_version.cpp)0
-rw-r--r--src/mongo/s/commands/cluster_is_db_grid_cmd.cpp72
-rw-r--r--src/mongo/s/commands/cluster_is_master_cmd.cpp87
-rw-r--r--src/mongo/s/commands/cluster_list_shards_cmd.cpp97
-rw-r--r--src/mongo/s/commands/cluster_move_chunk_cmd.cpp4
-rw-r--r--src/mongo/s/commands/cluster_remove_shard_cmd.cpp265
-rw-r--r--src/mongo/s/commands/cluster_reset_error_cmd.cpp (renamed from src/mongo/s/commands/cluster_reset_error.cpp)0
-rw-r--r--src/mongo/s/commands/cluster_whats_my_uri_cmd.cpp76
-rw-r--r--src/mongo/s/commands/cluster_write_cmd.cpp352
-rw-r--r--src/mongo/s/commands_admin.cpp487
14 files changed, 994 insertions, 681 deletions
diff --git a/src/mongo/SConscript b/src/mongo/SConscript
index 404cce94c19..fb8b81e15fd 100644
--- a/src/mongo/SConscript
+++ b/src/mongo/SConscript
@@ -854,7 +854,6 @@ env.Library('coreshard',
env.Library('mongoscore',
[
's/strategy.cpp',
- 's/commands_admin.cpp',
's/commands_public.cpp',
's/request.cpp',
's/client_info.cpp',
diff --git a/src/mongo/s/commands/SConscript b/src/mongo/s/commands/SConscript
index bcdb94d3088..6b691d97f07 100644
--- a/src/mongo/s/commands/SConscript
+++ b/src/mongo/s/commands/SConscript
@@ -5,25 +5,32 @@ Import("env")
env.Library(
target='cluster_commands',
source=[
- 'cluster_explain_cmd.cpp',
+ 'cluster_add_shard_cmd.cpp',
'cluster_enable_sharding_cmd.cpp',
+ 'cluster_explain_cmd.cpp',
'cluster_find_cmd.cpp',
'cluster_flush_router_config_cmd.cpp',
'cluster_fsync_cmd.cpp',
'cluster_get_last_error_cmd.cpp',
- 'cluster_get_shard_version.cpp',
+ 'cluster_get_prev_error_cmd.cpp',
+ 'cluster_get_shard_version_cmd.cpp',
'cluster_index_filter_cmd.cpp',
+ 'cluster_is_db_grid_cmd.cpp',
+ 'cluster_is_master_cmd.cpp',
'cluster_list_databases_cmd.cpp',
+ 'cluster_list_shards_cmd.cpp',
'cluster_merge_chunks_cmd.cpp',
'cluster_move_chunk_cmd.cpp',
'cluster_move_primary_cmd.cpp',
'cluster_netstat_cmd.cpp',
'cluster_plan_cache_cmd.cpp',
+ 'cluster_remove_shard_cmd.cpp',
'cluster_repl_set_get_status_cmd.cpp',
- 'cluster_reset_error.cpp',
+ 'cluster_reset_error_cmd.cpp',
'cluster_shard_collection_cmd.cpp',
'cluster_shutdown_cmd.cpp',
'cluster_split_collection_cmd.cpp',
+ 'cluster_whats_my_uri_cmd.cpp',
'cluster_write_cmd.cpp',
],
LIBDEPS=[
diff --git a/src/mongo/s/commands/cluster_add_shard_cmd.cpp b/src/mongo/s/commands/cluster_add_shard_cmd.cpp
new file mode 100644
index 00000000000..e80b9e76157
--- /dev/null
+++ b/src/mongo/s/commands/cluster_add_shard_cmd.cpp
@@ -0,0 +1,141 @@
+/**
+ * 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::kCommand
+
+#include "mongo/platform/basic.h"
+
+#include <vector>
+
+#include "mongo/db/audit.h"
+#include "mongo/db/commands.h"
+#include "mongo/s/grid.h"
+#include "mongo/s/type_shard.h"
+#include "mongo/util/log.h"
+
+namespace mongo {
+
+ using std::string;
+
+namespace {
+
+ class AddShardCmd : public Command {
+ public:
+ AddShardCmd() : Command("addShard", false, "addshard") { }
+
+ virtual bool slaveOk() const {
+ return true;
+ }
+
+ virtual bool adminOnly() const {
+ return true;
+ }
+
+ virtual bool isWriteCommandForConfigServer() const {
+ return false;
+ }
+
+ virtual void help(std::stringstream& help) const {
+ help << "add a new shard to the system";
+ }
+
+ virtual void addRequiredPrivileges(const std::string& dbname,
+ const BSONObj& cmdObj,
+ std::vector<Privilege>* out) {
+
+ ActionSet actions;
+ actions.addAction(ActionType::addShard);
+ out->push_back(Privilege(ResourcePattern::forClusterResource(), actions));
+ }
+
+ virtual bool run(OperationContext* txn,
+ const std::string& dbname,
+ BSONObj& cmdObj,
+ int options,
+ std::string& errmsg,
+ BSONObjBuilder& result,
+ bool fromRepl) {
+
+ // get replica set component hosts
+ ConnectionString servers = ConnectionString::parse(
+ cmdObj.firstElement().valuestrsafe(), errmsg);
+ if (!errmsg.empty()) {
+ log() << "addshard request " << cmdObj << " failed: " << errmsg;
+ return false;
+ }
+
+ // using localhost in server names implies every other process must use localhost addresses too
+ std::vector<HostAndPort> serverAddrs = servers.getServers();
+ for (size_t i = 0; i < serverAddrs.size(); i++) {
+ if (serverAddrs[i].isLocalHost() != grid.allowLocalHost()) {
+ errmsg = str::stream() <<
+ "Can't use localhost as a shard since all shards need to" <<
+ " communicate. Either use all shards and configdbs in localhost" <<
+ " or all in actual IPs. host: " << serverAddrs[i].toString() <<
+ " isLocalHost:" << serverAddrs[i].isLocalHost();
+
+ log() << "addshard request " << cmdObj
+ << " failed: attempt to mix localhosts and IPs";
+ return false;
+ }
+
+ // it's fine if mongods of a set all use default port
+ if (!serverAddrs[i].hasPort()) {
+ serverAddrs[i] = HostAndPort(serverAddrs[i].host(),
+ ServerGlobalParams::ShardServerPort);
+ }
+ }
+
+ // name is optional; addShard will provide one if needed
+ string name = "";
+ if (cmdObj["name"].type() == String) {
+ name = cmdObj["name"].valuestrsafe();
+ }
+
+ // maxSize is the space usage cap in a shard in MBs
+ long long maxSize = 0;
+ if (cmdObj[ShardType::maxSize()].isNumber()) {
+ maxSize = cmdObj[ShardType::maxSize()].numberLong();
+ }
+
+ audit::logAddShard(ClientBasic::getCurrent(), name, servers.toString(), maxSize);
+
+ if (!grid.addShard(&name, servers, maxSize, errmsg)) {
+ log() << "addshard request " << cmdObj << " failed: " << errmsg;
+ return false;
+ }
+
+ result << "shardAdded" << name;
+ return true;
+ }
+
+ } addShard;
+
+
+} // namespace
+} // namespace mongo
diff --git a/src/mongo/s/commands/cluster_get_prev_error_cmd.cpp b/src/mongo/s/commands/cluster_get_prev_error_cmd.cpp
new file mode 100644
index 00000000000..2e61db1683a
--- /dev/null
+++ b/src/mongo/s/commands/cluster_get_prev_error_cmd.cpp
@@ -0,0 +1,80 @@
+/**
+ * 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 <set>
+#include <string>
+
+#include "mongo/db/commands.h"
+#include "mongo/db/lasterror.h"
+#include "mongo/s/client/shard_connection.h"
+#include "mongo/s/client_info.h"
+
+namespace mongo {
+namespace {
+
+ class GetPrevErrorCmd : public Command {
+ public:
+ GetPrevErrorCmd() : Command("getPrevError", false, "getpreverror") { }
+
+ virtual bool isWriteCommandForConfigServer() const {
+ return false;
+ }
+
+ virtual bool slaveOk() const {
+ return true;
+ }
+
+ virtual void help(std::stringstream& help) const {
+ help << "get previous error (since last reseterror command)";
+ }
+
+ virtual void addRequiredPrivileges(const std::string& dbname,
+ const BSONObj& cmdObj,
+ std::vector<Privilege>* out) {
+
+ // No auth required
+ }
+
+ virtual bool run(OperationContext* txn,
+ const std::string& dbname,
+ BSONObj& cmdObj,
+ int options,
+ std::string& errmsg,
+ BSONObjBuilder& result,
+ bool fromRepl) {
+
+ errmsg += "getpreverror not supported for sharded environments";
+ return false;
+ }
+
+ } cmdGetPrevError;
+
+} // namespace
+} // namespace mongo
diff --git a/src/mongo/s/commands/cluster_get_shard_version.cpp b/src/mongo/s/commands/cluster_get_shard_version_cmd.cpp
index 6137310dd3e..6137310dd3e 100644
--- a/src/mongo/s/commands/cluster_get_shard_version.cpp
+++ b/src/mongo/s/commands/cluster_get_shard_version_cmd.cpp
diff --git a/src/mongo/s/commands/cluster_is_db_grid_cmd.cpp b/src/mongo/s/commands/cluster_is_db_grid_cmd.cpp
new file mode 100644
index 00000000000..e84b079937b
--- /dev/null
+++ b/src/mongo/s/commands/cluster_is_db_grid_cmd.cpp
@@ -0,0 +1,72 @@
+/**
+ * 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/db/commands.h"
+#include "mongo/util/net/sock.h"
+
+namespace mongo {
+namespace {
+
+ class IsDbGridCmd : public Command {
+ public:
+ IsDbGridCmd() : Command("isdbgrid") { }
+
+ virtual bool isWriteCommandForConfigServer() const {
+ return false;
+ }
+
+ virtual bool slaveOk() const {
+ return true;
+ }
+
+ virtual void addRequiredPrivileges(const std::string& dbname,
+ const BSONObj& cmdObj,
+ std::vector<Privilege>* out) {
+
+ // No auth required
+ }
+
+ virtual bool run(OperationContext* txn,
+ const std::string& dbname,
+ BSONObj& cmdObj,
+ int options,
+ std::string& errmsg,
+ BSONObjBuilder& result,
+ bool fromRepl) {
+
+ result.append("isdbgrid", 1);
+ result.append("hostname", getHostNameCached());
+ return true;
+ }
+
+ } isdbGrid;
+
+} // namespace
+} // namespace mongo
diff --git a/src/mongo/s/commands/cluster_is_master_cmd.cpp b/src/mongo/s/commands/cluster_is_master_cmd.cpp
new file mode 100644
index 00000000000..6bc41b14cc3
--- /dev/null
+++ b/src/mongo/s/commands/cluster_is_master_cmd.cpp
@@ -0,0 +1,87 @@
+/**
+ * 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/db/commands.h"
+#include "mongo/db/wire_version.h"
+#include "mongo/s/write_ops/batched_command_request.h"
+
+namespace mongo {
+namespace {
+
+ class CmdIsMaster : public Command {
+ public:
+ CmdIsMaster() : Command("isMaster", false, "ismaster") { }
+
+ virtual bool isWriteCommandForConfigServer() const {
+ return false;
+ }
+
+ virtual bool slaveOk() const {
+ return true;
+ }
+
+ virtual void help(std::stringstream& help) const {
+ help << "test if this is master half of a replica pair";
+ }
+
+ virtual void addRequiredPrivileges(const std::string& dbname,
+ const BSONObj& cmdObj,
+ std::vector<Privilege>* out) {
+
+ // No auth required
+ }
+
+ virtual bool run(OperationContext* txn,
+ const std::string& dbname,
+ BSONObj& cmdObj,
+ int options,
+ std::string& errmsg,
+ BSONObjBuilder& result,
+ bool fromRepl) {
+
+ result.appendBool("ismaster", true);
+ result.append("msg", "isdbgrid");
+ result.appendNumber("maxBsonObjectSize", BSONObjMaxUserSize);
+ result.appendNumber("maxMessageSizeBytes", MaxMessageSizeBytes);
+ result.appendNumber("maxWriteBatchSize", BatchedCommandRequest::kMaxWriteBatchSize);
+ result.appendDate("localTime", jsTime());
+
+ // Mongos tries to keep exactly the same version range of the server for which
+ // it is compiled.
+ result.append("maxWireVersion", maxWireVersion);
+ result.append("minWireVersion", minWireVersion);
+
+ return true;
+ }
+
+ } isMaster;
+
+} // namespace
+} // namespace mongo
diff --git a/src/mongo/s/commands/cluster_list_shards_cmd.cpp b/src/mongo/s/commands/cluster_list_shards_cmd.cpp
new file mode 100644
index 00000000000..3cccb6232a8
--- /dev/null
+++ b/src/mongo/s/commands/cluster_list_shards_cmd.cpp
@@ -0,0 +1,97 @@
+/**
+ * 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 <vector>
+
+#include "mongo/client/connpool.h"
+#include "mongo/db/commands.h"
+#include "mongo/s/config.h"
+#include "mongo/s/type_shard.h"
+
+namespace mongo {
+namespace {
+
+ class ListShardsCmd : public Command {
+ public:
+ ListShardsCmd() : Command("listShards", false, "listshards") { }
+
+ virtual bool slaveOk() const {
+ return true;
+ }
+
+ virtual bool adminOnly() const {
+ return true;
+ }
+
+ virtual bool isWriteCommandForConfigServer() const {
+ return false;
+ }
+
+ virtual void help(std::stringstream& help) const {
+ help << "list all shards of the system";
+ }
+
+ virtual void addRequiredPrivileges(const std::string& dbname,
+ const BSONObj& cmdObj,
+ std::vector<Privilege>* out) {
+
+ ActionSet actions;
+ actions.addAction(ActionType::listShards);
+ out->push_back(Privilege(ResourcePattern::forClusterResource(), actions));
+ }
+
+ virtual bool run(OperationContext* txn,
+ const std::string& dbname,
+ BSONObj& cmdObj,
+ int options,
+ std::string& errmsg,
+ BSONObjBuilder& result,
+ bool fromRepl) {
+
+ std::vector<BSONObj> all;
+
+ ScopedDbConnection conn(configServer.getPrimary().getConnString(), 30);
+ std::auto_ptr<DBClientCursor> cursor = conn->query(ShardType::ConfigNS, BSONObj());
+ while (cursor->more()) {
+ BSONObj o = cursor->next();
+ all.push_back(o);
+ }
+
+ result.append("shards", all);
+
+ conn.done();
+
+ return true;
+ }
+
+ } listShards;
+
+} // namespace
+} // namespace mongo
diff --git a/src/mongo/s/commands/cluster_move_chunk_cmd.cpp b/src/mongo/s/commands/cluster_move_chunk_cmd.cpp
index 51588058c32..10623a1c29e 100644
--- a/src/mongo/s/commands/cluster_move_chunk_cmd.cpp
+++ b/src/mongo/s/commands/cluster_move_chunk_cmd.cpp
@@ -176,7 +176,7 @@ namespace {
// Bounds
if (!info->getShardKeyPattern().isShardKey(bounds[0].Obj())
- || !info->getShardKeyPattern().isShardKey(bounds[1].Obj())) {
+ || !info->getShardKeyPattern().isShardKey(bounds[1].Obj())) {
errmsg = str::stream() << "shard key bounds " << "[" << bounds[0].Obj() << ","
<< bounds[1].Obj() << ")"
<< " are not valid for shard key pattern "
@@ -251,7 +251,7 @@ namespace {
return true;
}
- } moveChunkCmd;
+ } moveChunk;
} // namespace
} // namespace mongo
diff --git a/src/mongo/s/commands/cluster_remove_shard_cmd.cpp b/src/mongo/s/commands/cluster_remove_shard_cmd.cpp
new file mode 100644
index 00000000000..d93a8152a88
--- /dev/null
+++ b/src/mongo/s/commands/cluster_remove_shard_cmd.cpp
@@ -0,0 +1,265 @@
+/**
+ * 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::kCommand
+
+#include "mongo/platform/basic.h"
+
+#include <string>
+
+#include "mongo/client/connpool.h"
+#include "mongo/client/replica_set_monitor.h"
+#include "mongo/db/audit.h"
+#include "mongo/db/commands.h"
+#include "mongo/s/client/shard_connection.h"
+#include "mongo/s/cluster_write.h"
+#include "mongo/s/config.h"
+#include "mongo/s/grid.h"
+#include "mongo/s/shard.h"
+#include "mongo/s/type_chunk.h"
+#include "mongo/s/type_database.h"
+#include "mongo/s/type_shard.h"
+#include "mongo/util/log.h"
+
+namespace mongo {
+
+ using std::string;
+
+namespace {
+
+ BSONObj buildRemoveLogEntry(Shard s, bool isDraining) {
+ BSONObjBuilder details;
+ details.append("shard", s.getName());
+ details.append("isDraining", isDraining);
+
+ return details.obj();
+ }
+
+
+ class RemoveShardCmd : public Command {
+ public:
+ RemoveShardCmd() : Command("removeShard", false, "removeshard") { }
+
+ virtual bool slaveOk() const {
+ return true;
+ }
+
+ virtual bool adminOnly() const {
+ return true;
+ }
+
+ virtual bool isWriteCommandForConfigServer() const {
+ return false;
+ }
+
+ virtual void help(std::stringstream& help) const {
+ help << "remove a shard from the system.";
+ }
+
+ virtual void addRequiredPrivileges(const std::string& dbname,
+ const BSONObj& cmdObj,
+ std::vector<Privilege>* out) {
+
+ ActionSet actions;
+ actions.addAction(ActionType::removeShard);
+ out->push_back(Privilege(ResourcePattern::forClusterResource(), actions));
+ }
+
+ virtual bool run(OperationContext* txn,
+ const std::string& dbname,
+ BSONObj& cmdObj,
+ int options,
+ std::string& errmsg,
+ BSONObjBuilder& result,
+ bool fromRepl) {
+
+ const string target = cmdObj.firstElement().valuestrsafe();
+
+ Shard s = Shard::make(target);
+ if (!grid.knowAboutShard(s.getConnString())) {
+ errmsg = "unknown shard";
+ return false;
+ }
+
+ ScopedDbConnection conn(configServer.getPrimary().getConnString(), 30);
+
+ if (conn->count(ShardType::ConfigNS,
+ BSON(ShardType::name() << NE << s.getName()
+ << ShardType::draining(true)))) {
+ conn.done();
+ errmsg = "Can't have more than one draining shard at a time";
+ return false;
+ }
+
+ if (conn->count(ShardType::ConfigNS,
+ BSON(ShardType::name() << NE << s.getName())) == 0) {
+ conn.done();
+ errmsg = "Can't remove last shard";
+ return false;
+ }
+
+ BSONObj primaryDoc =
+ BSON(DatabaseType::name.ne("local") << DatabaseType::primary(s.getName()));
+
+ BSONObj dbInfo; // appended at end of result on success
+ {
+ boost::scoped_ptr<DBClientCursor> cursor(conn->query(DatabaseType::ConfigNS,
+ primaryDoc));
+ if (cursor->more()) {
+ // Skip block and allocations if empty
+ BSONObjBuilder dbInfoBuilder;
+ dbInfoBuilder.append("note",
+ "you need to drop or movePrimary these databases");
+
+ BSONArrayBuilder dbs(dbInfoBuilder.subarrayStart("dbsToMove"));
+ while (cursor->more()){
+ BSONObj db = cursor->nextSafe();
+ dbs.append(db[DatabaseType::name()]);
+ }
+ dbs.doneFast();
+
+ dbInfo = dbInfoBuilder.obj();
+ }
+ }
+
+ // If the server is not yet draining chunks, put it in draining mode.
+ BSONObj searchDoc = BSON(ShardType::name() << s.getName());
+ BSONObj drainingDoc =
+ BSON(ShardType::name() << s.getName() << ShardType::draining(true));
+
+ BSONObj shardDoc = conn->findOne(ShardType::ConfigNS, drainingDoc);
+ if (shardDoc.isEmpty()) {
+ log() << "going to start draining shard: " << s.getName();
+ BSONObj newStatus = BSON("$set" << BSON(ShardType::draining(true)));
+
+ Status status = clusterUpdate(ShardType::ConfigNS,
+ searchDoc,
+ newStatus,
+ false,
+ false,
+ NULL);
+ if (!status.isOK()) {
+ errmsg = status.reason();
+ log() << "error starting remove shard: " << s.getName()
+ << " err: " << errmsg;
+ return false;
+ }
+
+ BSONObj primaryLocalDoc = BSON(DatabaseType::name("local") <<
+ DatabaseType::primary(s.getName()));
+ PRINT(primaryLocalDoc);
+
+ if (conn->count(DatabaseType::ConfigNS, primaryLocalDoc)) {
+ log() << "This shard is listed as primary of local db. Removing entry.";
+
+ Status status = clusterDelete(DatabaseType::ConfigNS,
+ BSON(DatabaseType::name("local")),
+ 0,
+ NULL);
+ if (!status.isOK()) {
+ log() << "error removing local db: "
+ << status.reason();
+ return false;
+ }
+ }
+
+ Shard::reloadShardInfo();
+
+ result.append("msg", "draining started successfully");
+ result.append("state", "started");
+ result.append("shard", s.getName());
+ result.appendElements(dbInfo);
+
+ conn.done();
+
+ // Record start in changelog
+ configServer.logChange("removeShard.start",
+ "",
+ buildRemoveLogEntry(s, true));
+
+ return true;
+ }
+
+ // If the server has been completely drained, remove it from the ConfigDB. Check not
+ // only for chunks but also databases.
+ BSONObj shardIDDoc = BSON(ChunkType::shard(shardDoc[ShardType::name()].str()));
+ long long chunkCount = conn->count(ChunkType::ConfigNS, shardIDDoc);
+ long long dbCount = conn->count(DatabaseType::ConfigNS, primaryDoc);
+
+ if ((chunkCount == 0) && (dbCount == 0)) {
+ log() << "going to remove shard: " << s.getName();
+ audit::logRemoveShard(ClientBasic::getCurrent(), s.getName());
+
+ Status status = clusterDelete(ShardType::ConfigNS,
+ searchDoc,
+ 0,
+ NULL);
+ if (!status.isOK()) {
+ errmsg = status.reason();
+ log() << "error concluding remove shard: " << s.getName()
+ << " err: " << errmsg;
+ return false;
+ }
+
+ const string shardName = shardDoc[ShardType::name()].str();
+ Shard::removeShard(shardName);
+ shardConnectionPool.removeHost(shardName);
+ ReplicaSetMonitor::remove(shardName, true);
+
+ Shard::reloadShardInfo();
+
+ result.append("msg", "removeshard completed successfully");
+ result.append("state", "completed");
+ result.append("shard", s.getName());
+
+ conn.done();
+
+ // Record finish in changelog
+ configServer.logChange("removeShard", "", buildRemoveLogEntry(s, false));
+
+ return true;
+ }
+
+ // If the server is already in draining mode, just report on its progress.
+ // Report on databases (not just chunks) that are left too.
+ result.append("msg", "draining ongoing");
+ result.append("state", "ongoing");
+ BSONObjBuilder inner;
+ inner.append("chunks", chunkCount);
+ inner.append("dbs", dbCount);
+ result.append("remaining", inner.obj());
+ result.appendElements(dbInfo);
+
+ conn.done();
+ return true;
+ }
+
+ } removeShardCmd;
+
+} // namespace
+} // namespace mongo
diff --git a/src/mongo/s/commands/cluster_reset_error.cpp b/src/mongo/s/commands/cluster_reset_error_cmd.cpp
index c3096d367b1..c3096d367b1 100644
--- a/src/mongo/s/commands/cluster_reset_error.cpp
+++ b/src/mongo/s/commands/cluster_reset_error_cmd.cpp
diff --git a/src/mongo/s/commands/cluster_whats_my_uri_cmd.cpp b/src/mongo/s/commands/cluster_whats_my_uri_cmd.cpp
new file mode 100644
index 00000000000..2f9c3a618c5
--- /dev/null
+++ b/src/mongo/s/commands/cluster_whats_my_uri_cmd.cpp
@@ -0,0 +1,76 @@
+/**
+ * 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/db/commands.h"
+#include "mongo/s/client_info.h"
+#include "mongo/util/net/sock.h"
+
+namespace mongo {
+namespace {
+
+ class WhatsMyUriCmd : public Command {
+ public:
+ WhatsMyUriCmd() : Command("whatsmyuri") { }
+
+ virtual bool slaveOk() const {
+ return true;
+ }
+
+ virtual bool isWriteCommandForConfigServer() const {
+ return false;
+ }
+
+ virtual void help(std::stringstream &help) const {
+ help << "{whatsmyuri:1}";
+ }
+
+ virtual void addRequiredPrivileges(const std::string& dbname,
+ const BSONObj& cmdObj,
+ std::vector<Privilege>* out) {
+
+ // No auth required
+ }
+
+ virtual bool run(OperationContext* txn,
+ const std::string& dbname,
+ BSONObj& cmdObj,
+ int options,
+ std::string& errmsg,
+ BSONObjBuilder& result,
+ bool fromRepl) {
+
+ result << "you" << ClientInfo::get()->getRemote().toString();
+ return true;
+ }
+
+ } whatsMyUriCmd;
+
+} // namespace
+} // namespace mongo
diff --git a/src/mongo/s/commands/cluster_write_cmd.cpp b/src/mongo/s/commands/cluster_write_cmd.cpp
index 1b8828a4824..b6376980dbb 100644
--- a/src/mongo/s/commands/cluster_write_cmd.cpp
+++ b/src/mongo/s/commands/cluster_write_cmd.cpp
@@ -28,7 +28,6 @@
#include "mongo/platform/basic.h"
-#include "mongo/base/init.h"
#include "mongo/base/error_codes.h"
#include "mongo/db/client_basic.h"
#include "mongo/db/commands.h"
@@ -50,6 +49,8 @@ namespace mongo {
using std::stringstream;
using std::vector;
+namespace {
+
/**
* Base class for mongos write commands. Cluster write commands support batch writes and write
* concern, and return per-item error information. All cluster write commands use the entry
@@ -58,31 +59,32 @@ namespace mongo {
* Batch execution (targeting and dispatching) is performed by the BatchWriteExec class.
*/
class ClusterWriteCmd : public Command {
- MONGO_DISALLOW_COPYING(ClusterWriteCmd);
public:
-
virtual ~ClusterWriteCmd() {
+
}
- bool slaveOk() const {
+ virtual bool slaveOk() const {
return false;
}
- bool isWriteCommandForConfigServer() const { return false; }
+ virtual bool isWriteCommandForConfigServer() const {
+ return false;
+ }
- Status checkAuthForCommand( ClientBasic* client,
- const std::string& dbname,
- const BSONObj& cmdObj ) {
+ virtual Status checkAuthForCommand(ClientBasic* client,
+ const std::string& dbname,
+ const BSONObj& cmdObj) {
- Status status = auth::checkAuthForWriteCommand( client->getAuthorizationSession(),
- _writeType,
- NamespaceString( parseNs( dbname,
- cmdObj ) ),
- cmdObj );
+ Status status = auth::checkAuthForWriteCommand(client->getAuthorizationSession(),
+ _writeType,
+ NamespaceString(parseNs(dbname,
+ cmdObj)),
+ cmdObj);
// TODO: Remove this when we standardize GLE reporting from commands
- if ( !status.isOK() ) {
- setLastError( status.code(), status.reason().c_str() );
+ if (!status.isOK()) {
+ setLastError(status.code(), status.reason().c_str());
}
return status;
@@ -92,215 +94,189 @@ namespace mongo {
const std::string& dbname,
const BSONObj& cmdObj,
ExplainCommon::Verbosity verbosity,
- BSONObjBuilder* out) const;
-
- // Cluster write command entry point.
- bool run(OperationContext* txn, const string& dbname,
- BSONObj& cmdObj,
- int options,
- string& errmsg,
- BSONObjBuilder& result,
- bool fromRepl );
-
- protected:
-
- /**
- * Instantiates a command that can be invoked by "name", which will be capable of issuing
- * write batches of type "writeType", and will require privilege "action" to run.
- */
- ClusterWriteCmd( StringData name, BatchedCommandRequest::BatchType writeType ) :
- Command( name ), _writeType( writeType ) {
- }
-
- private:
-
- // Type of batch (e.g. insert).
- BatchedCommandRequest::BatchType _writeType;
- };
+ BSONObjBuilder* out) const {
- class ClusterCmdInsert : public ClusterWriteCmd {
- MONGO_DISALLOW_COPYING(ClusterCmdInsert);
- public:
- ClusterCmdInsert() :
- ClusterWriteCmd( "insert", BatchedCommandRequest::BatchType_Insert ) {
- }
+ BatchedCommandRequest request(_writeType);
- void help( stringstream& help ) const {
- help << "insert documents";
- }
- };
+ string errMsg;
+ if (!request.parseBSON(cmdObj, &errMsg) || !request.isValid(&errMsg)) {
+ return Status(ErrorCodes::FailedToParse, errMsg);
+ }
- class ClusterCmdUpdate : public ClusterWriteCmd {
- MONGO_DISALLOW_COPYING(ClusterCmdUpdate);
- public:
- ClusterCmdUpdate() :
- ClusterWriteCmd( "update", BatchedCommandRequest::BatchType_Update ) {
- }
+ // Fixup the namespace to be a full ns internally
+ const NamespaceString nss(dbname, request.getNS());
+ request.setNS(nss.ns());
- void help( stringstream& help ) const {
- help << "update documents";
- }
- };
+ // We can only explain write batches of size 1.
+ if (request.sizeWriteOps() != 1U) {
+ return Status(ErrorCodes::InvalidLength,
+ "explained write batches must be of size 1");
+ }
- class ClusterCmdDelete : public ClusterWriteCmd {
- MONGO_DISALLOW_COPYING(ClusterCmdDelete);
- public:
- ClusterCmdDelete() :
- ClusterWriteCmd( "delete", BatchedCommandRequest::BatchType_Delete ) {
- }
+ BSONObjBuilder explainCmdBob;
+ ClusterExplain::wrapAsExplain(cmdObj, verbosity, &explainCmdBob);
+
+ // We will time how long it takes to run the commands on the shards.
+ Timer timer;
+
+ // Target the command to the shards based on the singleton batch item.
+ BatchItemRef targetingBatchItem(&request, 0);
+ vector<Strategy::CommandResult> shardResults;
+ Status status = STRATEGY->commandOpWrite(dbname,
+ explainCmdBob.obj(),
+ targetingBatchItem,
+ &shardResults);
+ if (!status.isOK()) {
+ return status;
+ }
- void help( stringstream& help ) const {
- help << "delete documents";
+ return ClusterExplain::buildExplainResult(shardResults,
+ ClusterExplain::kWriteOnShards,
+ timer.millis(),
+ out);
}
- };
-
- //
- // Cluster write command implementation(s) below
- //
-
- bool ClusterWriteCmd::run(OperationContext* txn, const string& dbName,
- BSONObj& cmdObj,
- int options,
- string& errMsg,
- BSONObjBuilder& result,
- bool ) {
- BatchedCommandRequest request( _writeType );
- BatchedCommandResponse response;
- ClusterWriter writer( true /* autosplit */, 0 /* timeout */ );
-
- // NOTE: Sometimes this command is invoked with LE disabled for legacy writes
- LastError* cmdLastError = lastError.get( false );
+ virtual bool run(OperationContext* txn,
+ const string& dbname,
+ BSONObj& cmdObj,
+ int options,
+ string& errmsg,
+ BSONObjBuilder& result,
+ bool fromRepl) {
+
+ BatchedCommandRequest request(_writeType);
+ BatchedCommandResponse response;
+
+ ClusterWriter writer(true, 0);
+
+ // NOTE: Sometimes this command is invoked with LE disabled for legacy writes
+ LastError* cmdLastError = lastError.get(false);
+
+ {
+ // Disable the last error object for the duration of the write
+ LastError::Disabled disableLastError(cmdLastError);
+
+ // TODO: if we do namespace parsing, push this to the type
+ if (!request.parseBSON(cmdObj, &errmsg) || !request.isValid(&errmsg)) {
+ // Batch parse failure
+ response.setOk(false);
+ response.setErrCode(ErrorCodes::FailedToParse);
+ response.setErrMessage(errmsg);
+ }
+ else {
+ // Fixup the namespace to be a full ns internally
+ const NamespaceString nss(dbname, request.getNS());
+ request.setNSS(nss);
+
+ writer.write(request, &response);
+ }
+
+ dassert(response.isValid(NULL));
+ }
- {
- // Disable the last error object for the duration of the write
- LastError::Disabled disableLastError( cmdLastError );
+ if (cmdLastError) {
+ // Populate the lastError object based on the write response
+ cmdLastError->reset();
+ batchErrorToLastError(request, response, cmdLastError);
+ }
- // TODO: if we do namespace parsing, push this to the type
- if ( !request.parseBSON( cmdObj, &errMsg ) || !request.isValid( &errMsg ) ) {
+ size_t numAttempts;
- // Batch parse failure
- response.setOk( false );
- response.setErrCode( ErrorCodes::FailedToParse );
- response.setErrMessage( errMsg );
+ if (!response.getOk()) {
+ numAttempts = 0;
+ }
+ else if (request.getOrdered() && response.isErrDetailsSet()) {
+ // Add one failed attempt
+ numAttempts = response.getErrDetailsAt(0)->getIndex() + 1;
}
else {
+ numAttempts = request.sizeWriteOps();
+ }
- // Fixup the namespace to be a full ns internally
- NamespaceString nss( dbName, request.getNS() );
- request.setNSS( nss );
+ // TODO: increase opcounters by more than one
+ if (_writeType == BatchedCommandRequest::BatchType_Insert) {
+ for (size_t i = 0; i < numAttempts; ++i) {
+ globalOpCounters.gotInsert();
+ }
+ }
+ else if (_writeType == BatchedCommandRequest::BatchType_Update) {
+ for (size_t i = 0; i < numAttempts; ++i) {
+ globalOpCounters.gotUpdate();
+ }
+ }
+ else if (_writeType == BatchedCommandRequest::BatchType_Delete) {
+ for (size_t i = 0; i < numAttempts; ++i) {
+ globalOpCounters.gotDelete();
+ }
+ }
- writer.write( request, &response );
+ // Save the last opTimes written on each shard for this client, to allow GLE to work
+ if (ClientInfo::exists() && writer.getStats().hasShardStats()) {
+ ClientInfo* clientInfo = ClientInfo::get(NULL);
+ clientInfo->addHostOpTimes(writer.getStats().getShardStats().getWriteOpTimes());
}
- dassert( response.isValid( NULL ) );
+ // TODO
+ // There's a pending issue about how to report response here. If we use
+ // the command infra-structure, we should reuse the 'errmsg' field. But
+ // we have already filed that message inside the BatchCommandResponse.
+ // return response.getOk();
+ result.appendElements(response.toBSON());
+ return true;
}
- if ( cmdLastError ) {
- // Populate the lastError object based on the write response
- cmdLastError->reset();
- batchErrorToLastError( request, response, cmdLastError );
- }
+ protected:
+ /**
+ * Instantiates a command that can be invoked by "name", which will be capable of issuing
+ * write batches of type "writeType", and will require privilege "action" to run.
+ */
+ ClusterWriteCmd(StringData name, BatchedCommandRequest::BatchType writeType)
+ : Command(name),
+ _writeType(writeType) {
- size_t numAttempts;
- if ( !response.getOk() ) {
- numAttempts = 0;
- } else if ( request.getOrdered() && response.isErrDetailsSet() ) {
- numAttempts = response.getErrDetailsAt(0)->getIndex() + 1; // Add one failed attempt
- } else {
- numAttempts = request.sizeWriteOps();
}
- // TODO: increase opcounters by more than one
- if ( _writeType == BatchedCommandRequest::BatchType_Insert ) {
- for( size_t i = 0; i < numAttempts; ++i ) {
- globalOpCounters.gotInsert();
- }
- } else if ( _writeType == BatchedCommandRequest::BatchType_Update ) {
- for( size_t i = 0; i < numAttempts; ++i ) {
- globalOpCounters.gotUpdate();
- }
- } else if ( _writeType == BatchedCommandRequest::BatchType_Delete ) {
- for( size_t i = 0; i < numAttempts; ++i ) {
- globalOpCounters.gotDelete();
- }
- }
+ private:
+ // Type of batch (e.g. insert, update).
+ const BatchedCommandRequest::BatchType _writeType;
+ };
- // Save the last opTimes written on each shard for this client, to allow GLE to work
- if ( ClientInfo::exists() && writer.getStats().hasShardStats() ) {
- ClientInfo* clientInfo = ClientInfo::get( NULL );
- clientInfo->addHostOpTimes( writer.getStats().getShardStats().getWriteOpTimes() );
- }
- // TODO
- // There's a pending issue about how to report response here. If we use
- // the command infra-structure, we should reuse the 'errmsg' field. But
- // we have already filed that message inside the BatchCommandResponse.
- // return response.getOk();
- result.appendElements( response.toBSON() );
- return true;
- }
-
- Status ClusterWriteCmd::explain(OperationContext* txn,
- const std::string& dbname,
- const BSONObj& cmdObj,
- ExplainCommon::Verbosity verbosity,
- BSONObjBuilder* out) const {
-
- BatchedCommandRequest request(_writeType);
-
- string errMsg;
- if (!request.parseBSON(cmdObj, &errMsg) || !request.isValid(&errMsg)) {
- return Status(ErrorCodes::FailedToParse, errMsg);
- }
+ class ClusterCmdInsert : public ClusterWriteCmd {
+ public:
+ ClusterCmdInsert() : ClusterWriteCmd("insert", BatchedCommandRequest::BatchType_Insert) {
- // Fixup the namespace to be a full ns internally
- NamespaceString nss(dbname, request.getNS());
- request.setNS(nss.ns());
+ }
- // We can only explain write batches of size 1.
- if (request.sizeWriteOps() != 1U) {
- return Status(ErrorCodes::InvalidLength, "explained write batches must be of size 1");
+ void help(stringstream& help) const {
+ help << "insert documents";
}
- BSONObjBuilder explainCmdBob;
- ClusterExplain::wrapAsExplain(cmdObj, verbosity, &explainCmdBob);
+ } clusterInsertCmd;
- // We will time how long it takes to run the commands on the shards.
- Timer timer;
+ class ClusterCmdUpdate : public ClusterWriteCmd {
+ public:
+ ClusterCmdUpdate() : ClusterWriteCmd("update", BatchedCommandRequest::BatchType_Update) {
- // Target the command to the shards based on the singleton batch item.
- BatchItemRef targetingBatchItem(&request, 0);
- vector<Strategy::CommandResult> shardResults;
- Status status = STRATEGY->commandOpWrite(dbname,
- explainCmdBob.obj(),
- targetingBatchItem,
- &shardResults);
- if (!status.isOK())
- return status;
+ }
- long long millisElapsed = timer.millis();
+ void help( stringstream& help ) const {
+ help << "update documents";
+ }
- return ClusterExplain::buildExplainResult(shardResults,
- ClusterExplain::kWriteOnShards,
- millisElapsed,
- out);
- }
+ } clusterUpdateCmd;
- //
- // Register write commands at startup
- //
+ class ClusterCmdDelete : public ClusterWriteCmd {
+ public:
+ ClusterCmdDelete() : ClusterWriteCmd("delete", BatchedCommandRequest::BatchType_Delete) {
- namespace {
+ }
- MONGO_INITIALIZER(RegisterWriteCommands)(InitializerContext* context) {
- // Leaked intentionally: a Command registers itself when constructed.
- new ClusterCmdInsert();
- new ClusterCmdUpdate();
- new ClusterCmdDelete();
- return Status::OK();
+ void help(stringstream& help) const {
+ help << "delete documents";
}
- } // namespace
+ } clusterDeleteCmd;
+} // namespace
} // namespace mongo
diff --git a/src/mongo/s/commands_admin.cpp b/src/mongo/s/commands_admin.cpp
deleted file mode 100644
index ff1c0de862e..00000000000
--- a/src/mongo/s/commands_admin.cpp
+++ /dev/null
@@ -1,487 +0,0 @@
-/**
-* Copyright (C) 2008 10gen 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::kCommand
-
-#include "mongo/platform/basic.h"
-
-#include "mongo/db/commands.h"
-
-#include <boost/scoped_ptr.hpp>
-#include <boost/shared_ptr.hpp>
-
-#include "mongo/client/connpool.h"
-#include "mongo/client/dbclientcursor.h"
-#include "mongo/client/replica_set_monitor.h"
-#include "mongo/db/audit.h"
-#include "mongo/db/auth/action_set.h"
-#include "mongo/db/auth/action_type.h"
-#include "mongo/db/auth/authorization_manager.h"
-#include "mongo/db/auth/authorization_session.h"
-#include "mongo/db/auth/privilege.h"
-#include "mongo/db/dbmessage.h"
-#include "mongo/db/field_parser.h"
-#include "mongo/db/hasher.h"
-#include "mongo/db/index_names.h"
-#include "mongo/db/query/lite_parsed_query.h"
-#include "mongo/db/lasterror.h"
-#include "mongo/db/stats/counters.h"
-#include "mongo/db/wire_version.h"
-#include "mongo/db/write_concern.h"
-#include "mongo/db/write_concern_options.h"
-#include "mongo/s/chunk_manager.h"
-#include "mongo/s/client_info.h"
-#include "mongo/s/client/shard_connection.h"
-#include "mongo/s/cluster_write.h"
-#include "mongo/s/config.h"
-#include "mongo/s/dbclient_multi_command.h"
-#include "mongo/s/dbclient_shard_resolver.h"
-#include "mongo/s/distlock.h"
-#include "mongo/s/grid.h"
-#include "mongo/s/strategy.h"
-#include "mongo/s/type_chunk.h"
-#include "mongo/s/type_database.h"
-#include "mongo/s/type_shard.h"
-#include "mongo/s/write_ops/batch_downconvert.h"
-#include "mongo/s/write_ops/batch_write_exec.h"
-#include "mongo/s/write_ops/batched_command_request.h"
-#include "mongo/util/log.h"
-#include "mongo/util/net/listen.h"
-#include "mongo/util/net/message.h"
-#include "mongo/util/print.h"
-#include "mongo/util/processinfo.h"
-#include "mongo/util/ramlog.h"
-#include "mongo/util/stringutils.h"
-#include "mongo/util/timer.h"
-#include "mongo/util/version.h"
-
-namespace mongo {
-
- using boost::scoped_ptr;
- using boost::shared_ptr;
- using std::auto_ptr;
- using std::endl;
- using std::list;
- using std::map;
- using std::set;
- using std::string;
- using std::stringstream;
- using std::vector;
-
- namespace dbgrid_cmds {
-
- class GridAdminCmd : public Command {
- public:
- GridAdminCmd( const char * n ) : Command( n , false, tolowerString(n).c_str() ) {
-
- }
-
- virtual bool slaveOk() const {
- return true;
- }
-
- virtual bool adminOnly() const {
- return true;
- }
-
- virtual bool isWriteCommandForConfigServer() const {
- return false;
- }
- };
-
- // ------------ server level commands -------------
-
- class ListShardsCmd : public GridAdminCmd {
- public:
- ListShardsCmd() : GridAdminCmd("listShards") { }
- virtual void help( stringstream& help ) const {
- help << "list all shards of the system";
- }
- virtual void addRequiredPrivileges(const std::string& dbname,
- const BSONObj& cmdObj,
- std::vector<Privilege>* out) {
- ActionSet actions;
- actions.addAction(ActionType::listShards);
- out->push_back(Privilege(ResourcePattern::forClusterResource(), actions));
- }
- bool run(OperationContext* txn, const string& , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) {
- ScopedDbConnection conn(configServer.getPrimary().getConnString(), 30);
-
- vector<BSONObj> all;
- auto_ptr<DBClientCursor> cursor = conn->query( ShardType::ConfigNS , BSONObj() );
- while ( cursor->more() ) {
- BSONObj o = cursor->next();
- all.push_back( o );
- }
-
- result.append("shards" , all );
- conn.done();
-
- return true;
- }
- } listShardsCmd;
-
- /* a shard is a single mongod server or a replica pair. add it (them) to the cluster as a storage partition. */
- class AddShard : public GridAdminCmd {
- public:
- AddShard() : GridAdminCmd("addShard") { }
- virtual void help( stringstream& help ) const {
- help << "add a new shard to the system";
- }
- virtual void addRequiredPrivileges(const std::string& dbname,
- const BSONObj& cmdObj,
- std::vector<Privilege>* out) {
- ActionSet actions;
- actions.addAction(ActionType::addShard);
- out->push_back(Privilege(ResourcePattern::forClusterResource(), actions));
- }
- bool run(OperationContext* txn, const string& , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) {
- errmsg.clear();
-
- // get replica set component hosts
- ConnectionString servers = ConnectionString::parse( cmdObj.firstElement().valuestrsafe() , errmsg );
- if ( ! errmsg.empty() ) {
- log() << "addshard request " << cmdObj << " failed:" << errmsg << endl;
- return false;
- }
-
- // using localhost in server names implies every other process must use localhost addresses too
- vector<HostAndPort> serverAddrs = servers.getServers();
- for ( size_t i = 0 ; i < serverAddrs.size() ; i++ ) {
- if ( serverAddrs[i].isLocalHost() != grid.allowLocalHost() ) {
- errmsg = str::stream() <<
- "can't use localhost as a shard since all shards need to communicate. " <<
- "either use all shards and configdbs in localhost or all in actual IPs " <<
- " host: " << serverAddrs[i].toString() << " isLocalHost:" << serverAddrs[i].isLocalHost();
-
- log() << "addshard request " << cmdObj << " failed: attempt to mix localhosts and IPs" << endl;
- return false;
- }
-
- // it's fine if mongods of a set all use default port
- if ( ! serverAddrs[i].hasPort() ) {
- serverAddrs[i] = HostAndPort(serverAddrs[i].host(),
- ServerGlobalParams::ShardServerPort);
- }
- }
-
- // name is optional; addShard will provide one if needed
- string name = "";
- if ( cmdObj["name"].type() == String ) {
- name = cmdObj["name"].valuestrsafe();
- }
-
- // maxSize is the space usage cap in a shard in MBs
- long long maxSize = 0;
- if ( cmdObj[ ShardType::maxSize() ].isNumber() ) {
- maxSize = cmdObj[ ShardType::maxSize() ].numberLong();
- }
-
- audit::logAddShard(ClientBasic::getCurrent(), name, servers.toString(), maxSize);
- if ( ! grid.addShard( &name , servers , maxSize , errmsg ) ) {
- log() << "addshard request " << cmdObj << " failed: " << errmsg << endl;
- return false;
- }
-
- result << "shardAdded" << name;
- return true;
- }
-
- } addServer;
-
- /* See usage docs at:
- * http://dochub.mongodb.org/core/configuringsharding#ConfiguringSharding-Removingashard
- */
- class RemoveShardCmd : public GridAdminCmd {
- public:
- RemoveShardCmd() : GridAdminCmd("removeShard") { }
- virtual void help( stringstream& help ) const {
- help << "remove a shard to the system.";
- }
- virtual void addRequiredPrivileges(const std::string& dbname,
- const BSONObj& cmdObj,
- std::vector<Privilege>* out) {
- ActionSet actions;
- actions.addAction(ActionType::removeShard);
- out->push_back(Privilege(ResourcePattern::forClusterResource(), actions));
- }
- bool run(OperationContext* txn, const string& , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) {
- string target = cmdObj.firstElement().valuestrsafe();
- Shard s = Shard::make( target );
- if ( ! grid.knowAboutShard( s.getConnString() ) ) {
- errmsg = "unknown shard";
- return false;
- }
-
- ScopedDbConnection conn(configServer.getPrimary().getConnString(), 30);
-
- if (conn->count(ShardType::ConfigNS,
- BSON(ShardType::name() << NE << s.getName() <<
- ShardType::draining(true)))){
- conn.done();
- errmsg = "Can't have more than one draining shard at a time";
- return false;
- }
-
- if (conn->count(ShardType::ConfigNS, BSON(ShardType::name() << NE << s.getName())) == 0){
- conn.done();
- errmsg = "Can't remove last shard";
- return false;
- }
-
- BSONObj primaryDoc = BSON(DatabaseType::name.ne("local") <<
- DatabaseType::primary(s.getName()));
- BSONObj dbInfo; // appended at end of result on success
- {
- boost::scoped_ptr<DBClientCursor> cursor (conn->query(DatabaseType::ConfigNS, primaryDoc));
- if (cursor->more()) { // skip block and allocations if empty
- BSONObjBuilder dbInfoBuilder;
- dbInfoBuilder.append("note", "you need to drop or movePrimary these databases");
- BSONArrayBuilder dbs(dbInfoBuilder.subarrayStart("dbsToMove"));
-
- while (cursor->more()){
- BSONObj db = cursor->nextSafe();
- dbs.append(db[DatabaseType::name()]);
- }
- dbs.doneFast();
-
- dbInfo = dbInfoBuilder.obj();
- }
- }
-
- // If the server is not yet draining chunks, put it in draining mode.
- BSONObj searchDoc = BSON(ShardType::name() << s.getName());
- BSONObj drainingDoc = BSON(ShardType::name() << s.getName() << ShardType::draining(true));
- BSONObj shardDoc = conn->findOne(ShardType::ConfigNS, drainingDoc);
- if ( shardDoc.isEmpty() ) {
-
- // TODO prevent move chunks to this shard.
-
- log() << "going to start draining shard: " << s.getName() << endl;
- BSONObj newStatus = BSON( "$set" << BSON( ShardType::draining(true) ) );
-
- Status status = clusterUpdate( ShardType::ConfigNS,
- searchDoc,
- newStatus,
- false /* do no upsert */,
- false /* multi */,
- NULL );
-
- if ( !status.isOK() ) {
- errmsg = status.reason();
- log() << "error starting remove shard: " << s.getName()
- << " err: " << errmsg << endl;
- return false;
- }
-
- BSONObj primaryLocalDoc = BSON(DatabaseType::name("local") <<
- DatabaseType::primary(s.getName()));
- PRINT(primaryLocalDoc);
- if (conn->count(DatabaseType::ConfigNS, primaryLocalDoc)) {
- log() << "This shard is listed as primary of local db. Removing entry." << endl;
- Status status = clusterDelete( DatabaseType::ConfigNS,
- BSON(DatabaseType::name("local")),
- 0 /* limit */,
- NULL );
-
- if ( !status.isOK() ) {
- log() << "error removing local db: "
- << status.reason() << endl;
- return false;
- }
- }
-
- Shard::reloadShardInfo();
-
- result.append( "msg" , "draining started successfully" );
- result.append( "state" , "started" );
- result.append( "shard" , s.getName() );
- result.appendElements(dbInfo);
- conn.done();
-
- // Record start in changelog
- configServer.logChange( "removeShard.start",
- "",
- buildRemoveLogEntry( s, true ) );
-
- return true;
- }
-
- // If the server has been completely drained, remove it from the ConfigDB.
- // Check not only for chunks but also databases.
- BSONObj shardIDDoc = BSON(ChunkType::shard(shardDoc[ShardType::name()].str()));
- long long chunkCount = conn->count(ChunkType::ConfigNS, shardIDDoc);
- long long dbCount = conn->count( DatabaseType::ConfigNS , primaryDoc );
- if ( ( chunkCount == 0 ) && ( dbCount == 0 ) ) {
- log() << "going to remove shard: " << s.getName() << endl;
- audit::logRemoveShard(ClientBasic::getCurrent(), s.getName());
- Status status = clusterDelete( ShardType::ConfigNS,
- searchDoc,
- 0, // limit
- NULL );
-
- if ( !status.isOK() ) {
- errmsg = status.reason();
- log() << "error concluding remove shard: " << s.getName()
- << " err: " << errmsg << endl;
- return false;
- }
-
- string shardName = shardDoc[ ShardType::name() ].str();
- Shard::removeShard( shardName );
- shardConnectionPool.removeHost( shardName );
- ReplicaSetMonitor::remove( shardName, true );
- Shard::reloadShardInfo();
-
- result.append( "msg" , "removeshard completed successfully" );
- result.append( "state" , "completed" );
- result.append( "shard" , s.getName() );
- conn.done();
-
- // Record finish in changelog
- configServer.logChange( "removeShard", "", buildRemoveLogEntry( s, false ) );
-
- return true;
- }
-
- // If the server is already in draining mode, just report on its progress.
- // Report on databases (not just chunks) that are left too.
- result.append( "msg" , "draining ongoing" );
- result.append( "state" , "ongoing" );
- BSONObjBuilder inner;
- inner.append( "chunks" , chunkCount );
- inner.append( "dbs" , dbCount );
- result.append( "remaining" , inner.obj() );
- result.appendElements(dbInfo);
-
- conn.done();
- return true;
- }
- private:
- BSONObj buildRemoveLogEntry( Shard s, const bool isDraining ) {
- BSONObjBuilder details;
- details.append("shard", s.getName());
- details.append("isDraining", isDraining);
-
- return details.obj();
- }
- } removeShardCmd;
-
-
- // --------------- public commands ----------------
-
- class IsDbGridCmd : public Command {
- public:
- virtual bool isWriteCommandForConfigServer() const { return false; }
- virtual bool slaveOk() const {
- return true;
- }
- virtual void addRequiredPrivileges(const std::string& dbname,
- const BSONObj& cmdObj,
- std::vector<Privilege>* out) {} // No auth required
- IsDbGridCmd() : Command("isdbgrid") { }
- bool run(OperationContext* txn, const string& , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) {
- result.append("isdbgrid", 1);
- result.append("hostname", getHostNameCached());
- return true;
- }
- } isdbgrid;
-
- class CmdIsMaster : public Command {
- public:
- virtual bool isWriteCommandForConfigServer() const { return false; }
- virtual bool slaveOk() const {
- return true;
- }
- virtual void help( stringstream& help ) const {
- help << "test if this is master half of a replica pair";
- }
- virtual void addRequiredPrivileges(const std::string& dbname,
- const BSONObj& cmdObj,
- std::vector<Privilege>* out) {} // No auth required
- CmdIsMaster() : Command("isMaster" , false , "ismaster") { }
- virtual bool run(OperationContext* txn, const string& , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) {
- result.appendBool("ismaster", true );
- result.append("msg", "isdbgrid");
- result.appendNumber("maxBsonObjectSize", BSONObjMaxUserSize);
- result.appendNumber("maxMessageSizeBytes", MaxMessageSizeBytes);
- result.appendNumber("maxWriteBatchSize",
- BatchedCommandRequest::kMaxWriteBatchSize);
- result.appendDate("localTime", jsTime());
-
- // Mongos tries to keep exactly the same version range of the server it is
- // compiled for.
- result.append("maxWireVersion", maxWireVersion);
- result.append("minWireVersion", minWireVersion);
-
- return true;
- }
- } ismaster;
-
- class CmdWhatsMyUri : public Command {
- public:
- CmdWhatsMyUri() : Command("whatsmyuri") { }
- virtual bool slaveOk() const {
- return true;
- }
- virtual bool isWriteCommandForConfigServer() const { return false; }
- virtual void addRequiredPrivileges(const std::string& dbname,
- const BSONObj& cmdObj,
- std::vector<Privilege>* out) {} // No auth required
- virtual void help( stringstream &help ) const {
- help << "{whatsmyuri:1}";
- }
- virtual bool run(OperationContext* txn, const string& , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) {
- result << "you" << ClientInfo::get()->getRemote().toString();
- return true;
- }
- } cmdWhatsMyUri;
-
-
- class CmdShardingGetPrevError : public Command {
- public:
- virtual bool isWriteCommandForConfigServer() const { return false; }
- virtual bool slaveOk() const {
- return true;
- }
- virtual void help( stringstream& help ) const {
- help << "get previous error (since last reseterror command)";
- }
- virtual void addRequiredPrivileges(const std::string& dbname,
- const BSONObj& cmdObj,
- std::vector<Privilege>* out) {} // No auth required
- CmdShardingGetPrevError() : Command( "getPrevError" , false , "getpreverror") { }
- virtual bool run(OperationContext* txn, const string& , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) {
- errmsg += "getpreverror not supported for sharded environments";
- return false;
- }
- } cmdGetPrevError;
-
- }
-
-} // namespace mongo