2010-04-28 19:20:08 +02:00
|
|
|
// dbcommands_generic.cpp
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* 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/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* commands suited for any mongo server
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "pch.h"
|
|
|
|
#include "query.h"
|
|
|
|
#include "pdfile.h"
|
|
|
|
#include "jsobj.h"
|
|
|
|
#include "../bson/util/builder.h"
|
|
|
|
#include <time.h>
|
|
|
|
#include "introspect.h"
|
|
|
|
#include "btree.h"
|
|
|
|
#include "../util/lruishmap.h"
|
|
|
|
#include "../util/md5.hpp"
|
|
|
|
#include "../util/processinfo.h"
|
|
|
|
#include "json.h"
|
|
|
|
#include "repl.h"
|
|
|
|
#include "repl_block.h"
|
|
|
|
#include "replpair.h"
|
|
|
|
#include "commands.h"
|
|
|
|
#include "db.h"
|
|
|
|
#include "instance.h"
|
|
|
|
#include "lasterror.h"
|
|
|
|
#include "security.h"
|
|
|
|
#include "queryoptimizer.h"
|
|
|
|
#include "../scripting/engine.h"
|
|
|
|
#include "stats/counters.h"
|
|
|
|
#include "background.h"
|
2010-05-28 18:08:36 +02:00
|
|
|
#include "../util/version.h"
|
2010-04-28 19:20:08 +02:00
|
|
|
|
|
|
|
namespace mongo {
|
|
|
|
|
|
|
|
class CmdBuildInfo : public Command {
|
|
|
|
public:
|
|
|
|
CmdBuildInfo() : Command( "buildInfo", true, "buildinfo" ) {}
|
|
|
|
virtual bool slaveOk() const { return true; }
|
|
|
|
virtual bool adminOnly() const { return true; }
|
|
|
|
virtual LockType locktype() const { return NONE; }
|
|
|
|
virtual void help( stringstream &help ) const {
|
|
|
|
help << "get version #, etc.\n";
|
|
|
|
help << "{ buildinfo:1 }";
|
|
|
|
}
|
2010-05-03 22:25:34 +02:00
|
|
|
bool run(const string& dbname, BSONObj& jsobj, string& errmsg, BSONObjBuilder& result, bool fromRepl ){
|
2010-04-28 19:20:08 +02:00
|
|
|
result << "version" << versionString << "gitVersion" << gitVersion() << "sysInfo" << sysInfo();
|
|
|
|
result << "bits" << ( sizeof( int* ) == 4 ? 32 : 64 );
|
2010-10-07 06:12:32 +02:00
|
|
|
result.appendBool( "debug" , debug );
|
2010-10-11 17:26:41 +02:00
|
|
|
result.appendNumber("maxBsonObjectSize", BSONObjMaxUserSize);
|
2010-04-28 19:20:08 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} cmdBuildInfo;
|
|
|
|
|
2010-11-29 16:26:36 +01:00
|
|
|
/** experimental. either remove or add support in repl sets also. in a repl set, getting this setting from the
|
|
|
|
repl set config could make sense.
|
|
|
|
*/
|
2010-11-29 16:45:47 +01:00
|
|
|
unsigned replApplyBatchSize = 1;
|
2010-11-29 16:21:18 +01:00
|
|
|
|
2010-10-15 23:00:34 +02:00
|
|
|
class CmdGet : public Command {
|
|
|
|
public:
|
2010-11-23 01:52:44 +01:00
|
|
|
CmdGet() : Command( "getParameter" ) { }
|
2010-10-15 23:00:34 +02:00
|
|
|
virtual bool slaveOk() const { return true; }
|
|
|
|
virtual bool adminOnly() const { return true; }
|
|
|
|
virtual LockType locktype() const { return NONE; }
|
|
|
|
virtual void help( stringstream &help ) const {
|
|
|
|
help << "get administrative option(s)\nexample:\n";
|
2010-11-23 01:52:44 +01:00
|
|
|
help << "{ getParameter:1, notablescan:1 }\n";
|
2010-10-15 23:00:34 +02:00
|
|
|
help << "supported so far:\n";
|
2010-11-22 07:03:19 +01:00
|
|
|
help << " quiet\n";
|
2010-10-15 23:00:34 +02:00
|
|
|
help << " notablescan\n";
|
2010-11-22 07:03:19 +01:00
|
|
|
help << " logLevel\n";
|
2010-11-22 07:10:35 +01:00
|
|
|
help << " syncdelay\n";
|
2010-11-23 01:52:44 +01:00
|
|
|
help << "{ getParameter:'*' } to get everything\n";
|
2010-10-15 23:00:34 +02:00
|
|
|
}
|
2010-10-15 23:06:23 +02:00
|
|
|
bool run(const string& dbname, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
|
2010-11-29 16:21:18 +01:00
|
|
|
bool all = *cmdObj.firstElement().valuestrsafe() == '*';
|
2010-11-22 07:03:19 +01:00
|
|
|
|
|
|
|
int before = result.len();
|
|
|
|
|
|
|
|
if( all || cmdObj.hasElement("quiet") ) {
|
|
|
|
result.append("quiet", cmdLine.quiet );
|
|
|
|
}
|
2010-10-15 23:06:23 +02:00
|
|
|
if( all || cmdObj.hasElement("notablescan") ) {
|
2010-10-15 23:00:34 +02:00
|
|
|
result.append("notablescan", cmdLine.noTableScan);
|
|
|
|
}
|
2010-11-22 07:03:19 +01:00
|
|
|
if( all || cmdObj.hasElement("logLevel") ) {
|
|
|
|
result.append("logLevel", logLevel);
|
|
|
|
}
|
2010-11-22 07:10:35 +01:00
|
|
|
if( all || cmdObj.hasElement("syncdelay") ) {
|
|
|
|
result.append("syncdelay", cmdLine.syncdelay);
|
|
|
|
}
|
2010-11-29 16:21:18 +01:00
|
|
|
if( all || cmdObj.hasElement("replApplyBatchSize") ) {
|
|
|
|
result.append("replApplyBatchSize", replApplyBatchSize);
|
|
|
|
}
|
2010-11-22 07:03:19 +01:00
|
|
|
|
|
|
|
if ( before == result.len() ) {
|
2010-10-15 23:00:34 +02:00
|
|
|
errmsg = "no option found to get";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} cmdGet;
|
|
|
|
|
|
|
|
class CmdSet : public Command {
|
|
|
|
public:
|
2010-11-23 01:52:44 +01:00
|
|
|
CmdSet() : Command( "setParameter" ) { }
|
2010-10-15 23:00:34 +02:00
|
|
|
virtual bool slaveOk() const { return true; }
|
|
|
|
virtual bool adminOnly() const { return true; }
|
|
|
|
virtual LockType locktype() const { return NONE; }
|
|
|
|
virtual void help( stringstream &help ) const {
|
|
|
|
help << "set administrative option(s)\nexample:\n";
|
2010-11-23 01:52:44 +01:00
|
|
|
help << "{ setParameter:1, notablescan:true }\n";
|
2010-10-15 23:00:34 +02:00
|
|
|
help << "supported so far:\n";
|
|
|
|
help << " notablescan\n";
|
2010-11-22 07:03:19 +01:00
|
|
|
help << " logLevel\n";
|
|
|
|
help << " quiet\n";
|
2010-10-15 23:00:34 +02:00
|
|
|
}
|
|
|
|
bool run(const string& dbname, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl ){
|
2010-11-29 16:21:18 +01:00
|
|
|
int s = 0;
|
2010-10-15 23:00:34 +02:00
|
|
|
if( cmdObj.hasElement("notablescan") ) {
|
|
|
|
result.append("was", cmdLine.noTableScan);
|
|
|
|
cmdLine.noTableScan = cmdObj["notablescan"].Bool();
|
2010-11-29 16:21:18 +01:00
|
|
|
s++;
|
2010-10-15 23:00:34 +02:00
|
|
|
}
|
2010-11-29 16:21:18 +01:00
|
|
|
if( cmdObj.hasElement("quiet") ) {
|
2010-11-22 07:03:19 +01:00
|
|
|
result.append("was", cmdLine.quiet );
|
|
|
|
cmdLine.quiet = cmdObj["quiet"].Bool();
|
2010-11-29 16:21:18 +01:00
|
|
|
s++;
|
2010-11-22 07:03:19 +01:00
|
|
|
}
|
2010-11-29 16:21:18 +01:00
|
|
|
if( cmdObj.hasElement("syncdelay") ) {
|
2010-11-22 07:10:35 +01:00
|
|
|
result.append("was", cmdLine.syncdelay );
|
|
|
|
cmdLine.syncdelay = cmdObj["syncdelay"].Number();
|
2010-11-29 16:21:18 +01:00
|
|
|
s++;
|
2010-11-22 07:10:35 +01:00
|
|
|
}
|
2010-11-29 16:21:18 +01:00
|
|
|
if( cmdObj.hasElement( "logLevel" ) ) {
|
2010-11-22 07:03:19 +01:00
|
|
|
result.append("was", logLevel );
|
|
|
|
logLevel = cmdObj["logLevel"].numberInt();
|
2010-11-29 16:21:18 +01:00
|
|
|
s++;
|
2010-11-22 07:03:19 +01:00
|
|
|
}
|
2010-11-29 16:21:18 +01:00
|
|
|
if( cmdObj.hasElement( "replApplyBatchSize" ) ) {
|
|
|
|
result.append("was", replApplyBatchSize );
|
|
|
|
int b = cmdObj["replApplyBatchSize"].numberInt();
|
|
|
|
if( b < 1 || b > 1024 ) {
|
|
|
|
errmsg = "bad value";
|
|
|
|
return false;
|
|
|
|
}
|
2010-11-29 16:55:21 +01:00
|
|
|
// todo: should getParameters be not in dbcommands_generic?
|
|
|
|
assert( /*replSettings.slavedelay == 0 || */ b == 1 );
|
2010-11-29 16:21:18 +01:00
|
|
|
assert( replSettings.slave );
|
|
|
|
replApplyBatchSize = b;
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( s == 0 ) {
|
2010-10-15 23:00:34 +02:00
|
|
|
errmsg = "no option found to set";
|
|
|
|
return false;
|
|
|
|
}
|
2010-11-29 16:21:18 +01:00
|
|
|
|
2010-10-15 23:00:34 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} cmdSet;
|
2010-04-28 19:20:08 +02:00
|
|
|
|
|
|
|
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 LockType locktype() const { return NONE; }
|
|
|
|
virtual bool requiresAuth() { return false; }
|
2010-05-03 22:25:34 +02:00
|
|
|
virtual bool run(const string& badns, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool){
|
2010-04-28 19:20:08 +02:00
|
|
|
// 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 ){}
|
2010-10-08 21:48:36 +02:00
|
|
|
void help(stringstream& h) const { h << "return build level feature settings"; }
|
2010-04-28 19:20:08 +02:00
|
|
|
virtual bool slaveOk() const { return true; }
|
|
|
|
virtual bool readOnly(){ return true; }
|
|
|
|
virtual LockType locktype() const { return READ; }
|
2010-05-03 22:25:34 +02:00
|
|
|
virtual bool run(const string& ns, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl){
|
2010-04-28 19:20:08 +02:00
|
|
|
if ( globalScriptEngine ){
|
|
|
|
BSONObjBuilder bb( result.subobjStart( "js" ) );
|
|
|
|
result.append( "utf8" , globalScriptEngine->utf8Ok() );
|
|
|
|
bb.done();
|
|
|
|
}
|
2010-05-11 18:06:09 +02:00
|
|
|
if ( cmdObj["oidReset"].trueValue() ){
|
|
|
|
result.append( "oidMachineOld" , OID::staticMachine() );
|
|
|
|
OID::newState();
|
|
|
|
}
|
|
|
|
result.append( "oidMachine" , OID::staticMachine() );
|
2010-04-28 19:20:08 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
} featuresCmd;
|
|
|
|
|
|
|
|
class LogRotateCmd : public Command {
|
|
|
|
public:
|
|
|
|
LogRotateCmd() : Command( "logRotate" ){}
|
|
|
|
virtual LockType locktype() const { return NONE; }
|
|
|
|
virtual bool slaveOk() const { return true; }
|
|
|
|
virtual bool adminOnly() const { return true; }
|
2010-05-03 22:25:34 +02:00
|
|
|
virtual bool run(const string& ns, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
|
2010-04-28 19:20:08 +02:00
|
|
|
rotateLogs();
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
} 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 LockType locktype() const { return NONE; }
|
|
|
|
virtual bool slaveOk() const { return true; }
|
|
|
|
virtual bool adminOnly() const { return false; }
|
2010-05-03 22:25:34 +02:00
|
|
|
virtual bool run(const string& ns, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
|
2010-04-28 19:20:08 +02:00
|
|
|
BSONObjBuilder b( result.subobjStart( "commands" ) );
|
|
|
|
for ( map<string,Command*>::iterator i=_commands->begin(); i!=_commands->end(); ++i ){
|
|
|
|
Command * c = i->second;
|
2010-07-22 19:25:00 +02:00
|
|
|
|
|
|
|
// don't show oldnames
|
|
|
|
if (i->first != c->name)
|
|
|
|
continue;
|
|
|
|
|
2010-08-19 00:12:31 +02:00
|
|
|
BSONObjBuilder temp( b.subobjStart( c->name ) );
|
2010-04-28 19:20:08 +02:00
|
|
|
|
|
|
|
{
|
|
|
|
stringstream help;
|
|
|
|
c->help( help );
|
|
|
|
temp.append( "help" , help.str() );
|
|
|
|
}
|
|
|
|
temp.append( "lockType" , c->locktype() );
|
|
|
|
temp.append( "slaveOk" , c->slaveOk() );
|
|
|
|
temp.append( "adminOnly" , c->adminOnly() );
|
|
|
|
temp.done();
|
|
|
|
}
|
|
|
|
b.done();
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
} listCommandsCmd;
|
2010-07-27 03:48:20 +02:00
|
|
|
|
|
|
|
class CmdShutdown : public Command {
|
|
|
|
public:
|
|
|
|
virtual bool requiresAuth() { return true; }
|
|
|
|
virtual bool adminOnly() const { return true; }
|
|
|
|
virtual bool localHostOnlyIfNoAuth(const BSONObj& cmdObj) { return true; }
|
|
|
|
virtual bool logTheOp() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
virtual bool slaveOk() const {
|
|
|
|
return true;
|
|
|
|
}
|
2010-08-31 15:47:01 +02:00
|
|
|
virtual LockType locktype() const { return NONE; }
|
2010-07-27 03:48:20 +02:00
|
|
|
virtual void help( stringstream& help ) const {
|
|
|
|
help << "shutdown the database. must be ran against admin db and either (1) ran from localhost or (2) authenticated.\n";
|
|
|
|
}
|
|
|
|
CmdShutdown() : Command("shutdown") {}
|
|
|
|
bool run(const string& dbname, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
|
|
|
|
Client * c = currentClient.get();
|
2010-08-31 11:31:46 +02:00
|
|
|
if ( c ) {
|
2010-07-27 03:48:20 +02:00
|
|
|
c->shutdown();
|
2010-08-31 11:31:46 +02:00
|
|
|
}
|
2010-08-31 15:47:01 +02:00
|
|
|
|
2010-07-27 03:48:20 +02:00
|
|
|
log() << "terminating, shutdown command received" << endl;
|
2010-08-31 15:47:01 +02:00
|
|
|
|
2010-08-31 16:46:05 +02:00
|
|
|
dbexit( EXIT_CLEAN , "shutdown called" , true ); // this never returns
|
2010-08-31 15:47:01 +02:00
|
|
|
assert(0);
|
2010-07-27 03:48:20 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} cmdShutdown;
|
2010-07-27 06:57:38 +02:00
|
|
|
|
|
|
|
/* 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 logTheOp() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
virtual bool slaveOk() const {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
virtual LockType locktype() const { return NONE; }
|
|
|
|
CmdForceError() : Command("forceerror") {}
|
|
|
|
bool run(const string& dbnamne, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
|
|
|
|
uassert( 10038 , "forced error", false);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} cmdForceError;
|
|
|
|
|
2010-04-28 19:20:08 +02:00
|
|
|
}
|