summaryrefslogtreecommitdiff
path: root/src/mongo/db/commands/generic.cpp
diff options
context:
space:
mode:
authorAndrew Morrow <acm@mongodb.com>2015-10-18 12:09:57 -0400
committerAndrew Morrow <acm@mongodb.com>2015-10-19 15:21:58 -0400
commit0bd1fb89f07ae4c39d9ca50d0491fb2afe643a46 (patch)
tree51dd6c23b8e74a4c72c62f53e358f1e250df3708 /src/mongo/db/commands/generic.cpp
parent16b1fae1bb0b31303b987a91e61668ac4fa7b513 (diff)
downloadmongo-0bd1fb89f07ae4c39d9ca50d0491fb2afe643a46.tar.gz
SERVER-20995 Linking to command does not need command implementations
Diffstat (limited to 'src/mongo/db/commands/generic.cpp')
-rw-r--r--src/mongo/db/commands/generic.cpp485
1 files changed, 485 insertions, 0 deletions
diff --git a/src/mongo/db/commands/generic.cpp b/src/mongo/db/commands/generic.cpp
new file mode 100644
index 00000000000..47f47442452
--- /dev/null
+++ b/src/mongo/db/commands/generic.cpp
@@ -0,0 +1,485 @@
+/**
+* Copyright (C) 2012 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 <time.h>
+
+#include "mongo/bson/util/builder.h"
+#include "mongo/client/dbclient_rs.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/privilege.h"
+#include "mongo/db/background.h"
+#include "mongo/db/commands.h"
+#include "mongo/db/commands/shutdown.h"
+#include "mongo/db/db.h"
+#include "mongo/db/instance.h"
+#include "mongo/db/introspect.h"
+#include "mongo/db/jsobj.h"
+#include "mongo/db/json.h"
+#include "mongo/db/lasterror.h"
+#include "mongo/db/log_process_details.h"
+#include "mongo/db/server_options.h"
+#include "mongo/db/service_context.h"
+#include "mongo/db/stats/counters.h"
+#include "mongo/scripting/engine.h"
+#include "mongo/util/exit.h"
+#include "mongo/util/fail_point.h"
+#include "mongo/util/fail_point_service.h"
+#include "mongo/util/log.h"
+#include "mongo/util/md5.hpp"
+#include "mongo/util/ntservice.h"
+#include "mongo/util/processinfo.h"
+#include "mongo/util/ramlog.h"
+#include "mongo/util/version.h"
+
+namespace mongo {
+
+using std::endl;
+using std::string;
+using std::stringstream;
+using std::vector;
+
+class CmdBuildInfo : public Command {
+public:
+ CmdBuildInfo() : Command("buildInfo", true, "buildinfo") {}
+ virtual bool slaveOk() const {
+ return true;
+ }
+ virtual bool adminOnly() const {
+ return false;
+ }
+ 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 << "get version #, etc.\n";
+ help << "{ buildinfo:1 }";
+ }
+
+ bool run(OperationContext* txn,
+ const std::string& dbname,
+ BSONObj& jsobj,
+ int, // options
+ std::string& errmsg,
+ BSONObjBuilder& result) {
+ appendBuildInfo(result);
+ appendStorageEngineList(&result);
+ return true;
+ }
+
+} cmdBuildInfo;
+
+
+class PingCommand : public Command {
+public:
+ PingCommand() : Command("ping") {}
+ virtual bool slaveOk() const {
+ return true;
+ }
+ virtual void help(stringstream& help) const {
+ help << "a way to check that the server is alive. responds immediately even if server is "
+ "in a db lock.";
+ }
+ virtual bool isWriteCommandForConfigServer() const {
+ return false;
+ }
+ virtual void addRequiredPrivileges(const std::string& dbname,
+ const BSONObj& cmdObj,
+ std::vector<Privilege>* out) {} // No auth required
+ virtual bool run(OperationContext* txn,
+ const string& badns,
+ BSONObj& cmdObj,
+ int,
+ string& errmsg,
+ BSONObjBuilder& result) {
+ // IMPORTANT: Don't put anything in here that might lock db - including authentication
+ return true;
+ }
+} pingCmd;
+
+class FeaturesCmd : public Command {
+public:
+ FeaturesCmd() : Command("features", true) {}
+ void help(stringstream& h) const {
+ h << "return build level feature settings";
+ }
+ 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 bool run(OperationContext* txn,
+ const string& ns,
+ BSONObj& cmdObj,
+ int,
+ string& errmsg,
+ BSONObjBuilder& result) {
+ if (globalScriptEngine) {
+ BSONObjBuilder bb(result.subobjStart("js"));
+ result.append("utf8", globalScriptEngine->utf8Ok());
+ bb.done();
+ }
+ if (cmdObj["oidReset"].trueValue()) {
+ result.append("oidMachineOld", OID::getMachineId());
+ OID::regenMachineId();
+ }
+ result.append("oidMachine", OID::getMachineId());
+ return true;
+ }
+
+} featuresCmd;
+
+class HostInfoCmd : public Command {
+public:
+ HostInfoCmd() : Command("hostInfo", true) {}
+ virtual bool slaveOk() const {
+ return true;
+ }
+
+ virtual bool isWriteCommandForConfigServer() const {
+ return false;
+ }
+
+ virtual void help(stringstream& help) const {
+ help << "returns information about the daemon's host";
+ }
+ virtual void addRequiredPrivileges(const std::string& dbname,
+ const BSONObj& cmdObj,
+ std::vector<Privilege>* out) {
+ ActionSet actions;
+ actions.addAction(ActionType::hostInfo);
+ out->push_back(Privilege(ResourcePattern::forClusterResource(), actions));
+ }
+ bool run(OperationContext* txn,
+ const string& dbname,
+ BSONObj& cmdObj,
+ int,
+ string& errmsg,
+ BSONObjBuilder& result) {
+ ProcessInfo p;
+ BSONObjBuilder bSys, bOs;
+
+ bSys.appendDate("currentTime", jsTime());
+ bSys.append("hostname", prettyHostName());
+ bSys.append("cpuAddrSize", p.getAddrSize());
+ bSys.append("memSizeMB", static_cast<unsigned>(p.getMemSizeMB()));
+ bSys.append("numCores", p.getNumCores());
+ bSys.append("cpuArch", p.getArch());
+ bSys.append("numaEnabled", p.hasNumaEnabled());
+ bOs.append("type", p.getOsType());
+ bOs.append("name", p.getOsName());
+ bOs.append("version", p.getOsVersion());
+
+ result.append(StringData("system"), bSys.obj());
+ result.append(StringData("os"), bOs.obj());
+ p.appendSystemDetails(result);
+
+ return true;
+ }
+
+} hostInfoCmd;
+
+class LogRotateCmd : public Command {
+public:
+ LogRotateCmd() : Command("logRotate") {}
+ virtual bool isWriteCommandForConfigServer() const {
+ return false;
+ }
+ virtual bool slaveOk() const {
+ return true;
+ }
+ virtual bool adminOnly() const {
+ return true;
+ }
+ virtual void addRequiredPrivileges(const std::string& dbname,
+ const BSONObj& cmdObj,
+ std::vector<Privilege>* out) {
+ ActionSet actions;
+ actions.addAction(ActionType::logRotate);
+ out->push_back(Privilege(ResourcePattern::forClusterResource(), actions));
+ }
+ virtual bool run(OperationContext* txn,
+ const string& ns,
+ BSONObj& cmdObj,
+ int,
+ string& errmsg,
+ BSONObjBuilder& result) {
+ bool didRotate = rotateLogs(serverGlobalParams.logRenameOnRotate);
+ if (didRotate)
+ logProcessDetailsForLogRotate();
+ return didRotate;
+ }
+
+} logRotateCmd;
+
+class ListCommandsCmd : public Command {
+public:
+ virtual void help(stringstream& help) const {
+ help << "get a list of all db commands";
+ }
+ ListCommandsCmd() : Command("listCommands", false) {}
+ virtual bool isWriteCommandForConfigServer() const {
+ return false;
+ }
+ virtual bool slaveOk() const {
+ return true;
+ }
+ virtual bool adminOnly() const {
+ return false;
+ }
+ virtual void addRequiredPrivileges(const std::string& dbname,
+ const BSONObj& cmdObj,
+ std::vector<Privilege>* out) {} // No auth required
+ virtual bool run(OperationContext* txn,
+ const string& ns,
+ BSONObj& cmdObj,
+ int,
+ string& errmsg,
+ BSONObjBuilder& result) {
+ // sort the commands before building the result BSON
+ std::vector<Command*> commands;
+ for (CommandMap::const_iterator it = _commands->begin(); it != _commands->end(); ++it) {
+ // don't show oldnames
+ if (it->first == it->second->name)
+ commands.push_back(it->second);
+ }
+ std::sort(commands.begin(),
+ commands.end(),
+ [](Command* lhs, Command* rhs) { return (lhs->name) < (rhs->name); });
+
+ BSONObjBuilder b(result.subobjStart("commands"));
+ for (const auto& c : commands) {
+ BSONObjBuilder temp(b.subobjStart(c->name));
+
+ {
+ stringstream help;
+ c->help(help);
+ temp.append("help", help.str());
+ }
+ temp.append("slaveOk", c->slaveOk());
+ temp.append("adminOnly", c->adminOnly());
+ // optionally indicates that the command can be forced to run on a slave/secondary
+ if (c->slaveOverrideOk())
+ temp.append("slaveOverrideOk", c->slaveOverrideOk());
+ temp.done();
+ }
+ b.done();
+
+ return 1;
+ }
+
+} listCommandsCmd;
+
+namespace {
+MONGO_FP_DECLARE(crashOnShutdown);
+
+int* volatile illegalAddress;
+} // namespace
+
+void CmdShutdown::addRequiredPrivileges(const std::string& dbname,
+ const BSONObj& cmdObj,
+ std::vector<Privilege>* out) {
+ ActionSet actions;
+ actions.addAction(ActionType::shutdown);
+ out->push_back(Privilege(ResourcePattern::forClusterResource(), actions));
+}
+
+void CmdShutdown::shutdownHelper() {
+ MONGO_FAIL_POINT_BLOCK(crashOnShutdown, crashBlock) {
+ const std::string crashHow = crashBlock.getData()["how"].str();
+ if (crashHow == "fault") {
+ ++*illegalAddress;
+ }
+ ::abort();
+ }
+
+ log() << "terminating, shutdown command received";
+
+#if defined(_WIN32)
+ // Signal the ServiceMain thread to shutdown.
+ if (ntservice::shouldStartService()) {
+ signalShutdown();
+
+ // Client expects us to abruptly close the socket as part of exiting
+ // so this function is not allowed to return.
+ // The ServiceMain thread will quit for us so just sleep until it does.
+ while (true)
+ sleepsecs(60); // Loop forever
+ } else
+#endif
+ {
+ exitCleanly(EXIT_CLEAN); // this never returns
+ invariant(false);
+ }
+}
+
+/* for testing purposes only */
+class CmdForceError : public Command {
+public:
+ virtual void help(stringstream& help) const {
+ help << "for testing purposes only. forces a user assertion exception";
+ }
+ 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
+ CmdForceError() : Command("forceerror") {}
+ bool run(OperationContext* txn,
+ const string& dbnamne,
+ BSONObj& cmdObj,
+ int,
+ string& errmsg,
+ BSONObjBuilder& result) {
+ LastError::get(cc()).setLastError(10038, "forced error");
+ return false;
+ }
+} cmdForceError;
+
+class GetLogCmd : public Command {
+public:
+ GetLogCmd() : Command("getLog") {}
+
+ virtual bool slaveOk() const {
+ return true;
+ }
+ virtual bool isWriteCommandForConfigServer() const {
+ return false;
+ }
+ virtual bool adminOnly() const {
+ return true;
+ }
+ virtual void addRequiredPrivileges(const std::string& dbname,
+ const BSONObj& cmdObj,
+ std::vector<Privilege>* out) {
+ ActionSet actions;
+ actions.addAction(ActionType::getLog);
+ out->push_back(Privilege(ResourcePattern::forClusterResource(), actions));
+ }
+ virtual void help(stringstream& help) const {
+ help << "{ getLog : '*' } OR { getLog : 'global' }";
+ }
+
+ virtual bool run(OperationContext* txn,
+ const string& dbname,
+ BSONObj& cmdObj,
+ int,
+ string& errmsg,
+ BSONObjBuilder& result) {
+ BSONElement val = cmdObj.firstElement();
+ if (val.type() != String) {
+ return appendCommandStatus(
+ result,
+ Status(ErrorCodes::TypeMismatch,
+ str::stream() << "Argument to getLog must be of type String; found "
+ << val.toString(false) << " of type "
+ << typeName(val.type())));
+ }
+
+ string p = val.String();
+ if (p == "*") {
+ vector<string> names;
+ RamLog::getNames(names);
+
+ BSONArrayBuilder arr;
+ for (unsigned i = 0; i < names.size(); i++) {
+ arr.append(names[i]);
+ }
+
+ result.appendArray("names", arr.arr());
+ } else {
+ RamLog* ramlog = RamLog::getIfExists(p);
+ if (!ramlog) {
+ errmsg = str::stream() << "no RamLog named: " << p;
+ return false;
+ }
+ RamLog::LineIterator rl(ramlog);
+
+ result.appendNumber("totalLinesWritten", rl.getTotalLinesWritten());
+
+ BSONArrayBuilder arr(result.subarrayStart("log"));
+ while (rl.more())
+ arr.append(rl.next());
+ arr.done();
+ }
+ return true;
+ }
+
+} getLogCmd;
+
+class CmdGetCmdLineOpts : Command {
+public:
+ CmdGetCmdLineOpts() : Command("getCmdLineOpts") {}
+ void help(stringstream& h) const {
+ h << "get argv";
+ }
+ virtual bool isWriteCommandForConfigServer() const {
+ return false;
+ }
+ virtual bool adminOnly() const {
+ return true;
+ }
+ virtual bool slaveOk() const {
+ return true;
+ }
+ virtual void addRequiredPrivileges(const std::string& dbname,
+ const BSONObj& cmdObj,
+ std::vector<Privilege>* out) {
+ ActionSet actions;
+ actions.addAction(ActionType::getCmdLineOpts);
+ out->push_back(Privilege(ResourcePattern::forClusterResource(), actions));
+ }
+ virtual bool run(OperationContext* txn,
+ const string&,
+ BSONObj& cmdObj,
+ int,
+ string& errmsg,
+ BSONObjBuilder& result) {
+ result.append("argv", serverGlobalParams.argvArray);
+ result.append("parsed", serverGlobalParams.parsedOpts);
+ return true;
+ }
+
+} cmdGetCmdLineOpts;
+}