summaryrefslogtreecommitdiff
path: root/src/mongo/db/repl/replset_commands.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/repl/replset_commands.cpp')
-rw-r--r--src/mongo/db/repl/replset_commands.cpp1365
1 files changed, 674 insertions, 691 deletions
diff --git a/src/mongo/db/repl/replset_commands.cpp b/src/mongo/db/repl/replset_commands.cpp
index 600fbfe52a8..c26bed4775b 100644
--- a/src/mongo/db/repl/replset_commands.cpp
+++ b/src/mongo/db/repl/replset_commands.cpp
@@ -61,757 +61,740 @@
namespace mongo {
namespace repl {
- using std::string;
- using std::stringstream;
-
- // Testing only, enabled via command-line.
- class CmdReplSetTest : public ReplSetCommand {
- public:
- virtual void help( stringstream &help ) const {
- help << "Just for regression tests.\n";
- }
- // No auth needed because it only works when enabled via command line.
- virtual Status checkAuthForCommand(ClientBasic* client,
- const std::string& dbname,
- const BSONObj& cmdObj) {
- return Status::OK();
- }
- CmdReplSetTest() : ReplSetCommand("replSetTest") { }
- virtual bool run(OperationContext* txn,
- const string&,
- BSONObj& cmdObj,
- int,
- string& errmsg,
- BSONObjBuilder& result) {
- log() << "replSetTest command received: " << cmdObj.toString();
-
- if( cmdObj.hasElement("forceInitialSyncFailure") ) {
- replSetForceInitialSyncFailure = (unsigned) cmdObj["forceInitialSyncFailure"].Number();
- return true;
- }
-
- Status status = getGlobalReplicationCoordinator()->checkReplEnabledForCommand(&result);
- if (!status.isOK())
- return appendCommandStatus(result, status);
-
- return false;
- }
- };
- MONGO_INITIALIZER(RegisterReplSetTestCmd)(InitializerContext* context) {
- if (Command::testCommandsEnabled) {
- // Leaked intentionally: a Command registers itself when constructed.
- new CmdReplSetTest();
- }
+using std::string;
+using std::stringstream;
+
+// Testing only, enabled via command-line.
+class CmdReplSetTest : public ReplSetCommand {
+public:
+ virtual void help(stringstream& help) const {
+ help << "Just for regression tests.\n";
+ }
+ // No auth needed because it only works when enabled via command line.
+ virtual Status checkAuthForCommand(ClientBasic* client,
+ const std::string& dbname,
+ const BSONObj& cmdObj) {
return Status::OK();
}
+ CmdReplSetTest() : ReplSetCommand("replSetTest") {}
+ virtual bool run(OperationContext* txn,
+ const string&,
+ BSONObj& cmdObj,
+ int,
+ string& errmsg,
+ BSONObjBuilder& result) {
+ log() << "replSetTest command received: " << cmdObj.toString();
+
+ if (cmdObj.hasElement("forceInitialSyncFailure")) {
+ replSetForceInitialSyncFailure = (unsigned)cmdObj["forceInitialSyncFailure"].Number();
+ return true;
+ }
- /** get rollback id. used to check if a rollback happened during some interval of time.
- as consumed, the rollback id is not in any particular order, it simply changes on each rollback.
- @see incRBID()
- */
- class CmdReplSetGetRBID : public ReplSetCommand {
- public:
- CmdReplSetGetRBID() : ReplSetCommand("replSetGetRBID") {}
- virtual bool run(OperationContext* txn,
- const string&,
- BSONObj& cmdObj,
- int,
- string& errmsg,
- BSONObjBuilder& result) {
- Status status = getGlobalReplicationCoordinator()->checkReplEnabledForCommand(&result);
- if (!status.isOK())
- return appendCommandStatus(result, status);
-
- status = getGlobalReplicationCoordinator()->processReplSetGetRBID(&result);
+ Status status = getGlobalReplicationCoordinator()->checkReplEnabledForCommand(&result);
+ if (!status.isOK())
return appendCommandStatus(result, status);
- }
- } cmdReplSetRBID;
-
- class CmdReplSetGetStatus : public ReplSetCommand {
- public:
- virtual void help( stringstream &help ) const {
- help << "Report status of a replica set from the POV of this server\n";
- help << "{ replSetGetStatus : 1 }";
- help << "\nhttp://dochub.mongodb.org/core/replicasetcommands";
- }
- virtual Status checkAuthForCommand(ClientBasic* client,
- const std::string& dbname,
- const BSONObj& cmdObj) {
- ActionSet actions;
- actions.addAction(ActionType::replSetGetStatus);
- if (!AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
- ResourcePattern::forClusterResource(), actions)) {
- return Status(ErrorCodes::Unauthorized, "Unauthorized");
- }
- return Status::OK();
- }
- CmdReplSetGetStatus() : ReplSetCommand("replSetGetStatus", true) { }
- virtual bool run(OperationContext* txn,
- const string&,
- BSONObj& cmdObj,
- int,
- string& errmsg,
- BSONObjBuilder& result) {
- if ( cmdObj["forShell"].trueValue() )
- LastError::get(txn->getClient()).disable();
-
- Status status = getGlobalReplicationCoordinator()->checkReplEnabledForCommand(&result);
- if (!status.isOK())
- return appendCommandStatus(result, status);
- status = getGlobalReplicationCoordinator()->processReplSetGetStatus(&result);
+ return false;
+ }
+};
+MONGO_INITIALIZER(RegisterReplSetTestCmd)(InitializerContext* context) {
+ if (Command::testCommandsEnabled) {
+ // Leaked intentionally: a Command registers itself when constructed.
+ new CmdReplSetTest();
+ }
+ return Status::OK();
+}
+
+/** get rollback id. used to check if a rollback happened during some interval of time.
+ as consumed, the rollback id is not in any particular order, it simply changes on each rollback.
+ @see incRBID()
+*/
+class CmdReplSetGetRBID : public ReplSetCommand {
+public:
+ CmdReplSetGetRBID() : ReplSetCommand("replSetGetRBID") {}
+ virtual bool run(OperationContext* txn,
+ const string&,
+ BSONObj& cmdObj,
+ int,
+ string& errmsg,
+ BSONObjBuilder& result) {
+ Status status = getGlobalReplicationCoordinator()->checkReplEnabledForCommand(&result);
+ if (!status.isOK())
return appendCommandStatus(result, status);
+
+ status = getGlobalReplicationCoordinator()->processReplSetGetRBID(&result);
+ return appendCommandStatus(result, status);
+ }
+} cmdReplSetRBID;
+
+class CmdReplSetGetStatus : public ReplSetCommand {
+public:
+ virtual void help(stringstream& help) const {
+ help << "Report status of a replica set from the POV of this server\n";
+ help << "{ replSetGetStatus : 1 }";
+ help << "\nhttp://dochub.mongodb.org/core/replicasetcommands";
+ }
+ virtual Status checkAuthForCommand(ClientBasic* client,
+ const std::string& dbname,
+ const BSONObj& cmdObj) {
+ ActionSet actions;
+ actions.addAction(ActionType::replSetGetStatus);
+ if (!AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
+ ResourcePattern::forClusterResource(), actions)) {
+ return Status(ErrorCodes::Unauthorized, "Unauthorized");
}
- } cmdReplSetGetStatus;
-
- class CmdReplSetGetConfig : public ReplSetCommand {
- public:
- virtual void help( stringstream &help ) const {
- help << "Returns the current replica set configuration";
- help << "{ replSetGetConfig : 1 }";
- help << "\nhttp://dochub.mongodb.org/core/replicasetcommands";
- }
- virtual Status checkAuthForCommand(ClientBasic* client,
- const std::string& dbname,
- const BSONObj& cmdObj) {
- ActionSet actions;
- actions.addAction(ActionType::replSetGetConfig);
- if (!AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
- ResourcePattern::forClusterResource(), actions)) {
- return Status(ErrorCodes::Unauthorized, "Unauthorized");
- }
- return Status::OK();
- }
- CmdReplSetGetConfig() : ReplSetCommand("replSetGetConfig", true) { }
- virtual bool run(OperationContext* txn,
- const string&,
- BSONObj& cmdObj,
- int,
- string& errmsg,
- BSONObjBuilder& result) {
- Status status = getGlobalReplicationCoordinator()->checkReplEnabledForCommand(&result);
- if (!status.isOK())
- return appendCommandStatus(result, status);
+ return Status::OK();
+ }
+ CmdReplSetGetStatus() : ReplSetCommand("replSetGetStatus", true) {}
+ virtual bool run(OperationContext* txn,
+ const string&,
+ BSONObj& cmdObj,
+ int,
+ string& errmsg,
+ BSONObjBuilder& result) {
+ if (cmdObj["forShell"].trueValue())
+ LastError::get(txn->getClient()).disable();
+
+ Status status = getGlobalReplicationCoordinator()->checkReplEnabledForCommand(&result);
+ if (!status.isOK())
+ return appendCommandStatus(result, status);
- getGlobalReplicationCoordinator()->processReplSetGetConfig(&result);
- return true;
+ status = getGlobalReplicationCoordinator()->processReplSetGetStatus(&result);
+ return appendCommandStatus(result, status);
+ }
+} cmdReplSetGetStatus;
+
+class CmdReplSetGetConfig : public ReplSetCommand {
+public:
+ virtual void help(stringstream& help) const {
+ help << "Returns the current replica set configuration";
+ help << "{ replSetGetConfig : 1 }";
+ help << "\nhttp://dochub.mongodb.org/core/replicasetcommands";
+ }
+ virtual Status checkAuthForCommand(ClientBasic* client,
+ const std::string& dbname,
+ const BSONObj& cmdObj) {
+ ActionSet actions;
+ actions.addAction(ActionType::replSetGetConfig);
+ if (!AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
+ ResourcePattern::forClusterResource(), actions)) {
+ return Status(ErrorCodes::Unauthorized, "Unauthorized");
}
- } cmdReplSetGetConfig;
+ return Status::OK();
+ }
+ CmdReplSetGetConfig() : ReplSetCommand("replSetGetConfig", true) {}
+ virtual bool run(OperationContext* txn,
+ const string&,
+ BSONObj& cmdObj,
+ int,
+ string& errmsg,
+ BSONObjBuilder& result) {
+ Status status = getGlobalReplicationCoordinator()->checkReplEnabledForCommand(&result);
+ if (!status.isOK())
+ return appendCommandStatus(result, status);
+
+ getGlobalReplicationCoordinator()->processReplSetGetConfig(&result);
+ return true;
+ }
+} cmdReplSetGetConfig;
namespace {
- HostAndPort someHostAndPortForMe() {
- const char* ips = serverGlobalParams.bind_ip.c_str();
- while (*ips) {
- std::string ip;
- const char* comma = strchr(ips, ',');
- if (comma) {
- ip = std::string(ips, comma - ips);
- ips = comma + 1;
- }
- else {
- ip = std::string(ips);
- ips = "";
- }
- HostAndPort h = HostAndPort(ip, serverGlobalParams.port);
- if (!h.isLocalHost()) {
- return h;
- }
+HostAndPort someHostAndPortForMe() {
+ const char* ips = serverGlobalParams.bind_ip.c_str();
+ while (*ips) {
+ std::string ip;
+ const char* comma = strchr(ips, ',');
+ if (comma) {
+ ip = std::string(ips, comma - ips);
+ ips = comma + 1;
+ } else {
+ ip = std::string(ips);
+ ips = "";
+ }
+ HostAndPort h = HostAndPort(ip, serverGlobalParams.port);
+ if (!h.isLocalHost()) {
+ return h;
}
+ }
+
+ std::string h = getHostName();
+ verify(!h.empty());
+ verify(h != "localhost");
+ return HostAndPort(h, serverGlobalParams.port);
+}
+
+void parseReplSetSeedList(ReplicationCoordinatorExternalState* externalState,
+ const std::string& replSetString,
+ std::string* setname,
+ std::vector<HostAndPort>* seeds) {
+ const char* p = replSetString.c_str();
+ const char* slash = strchr(p, '/');
+ std::set<HostAndPort> seedSet;
+ if (slash) {
+ *setname = string(p, slash - p);
+ } else {
+ *setname = p;
+ }
- std::string h = getHostName();
- verify(!h.empty());
- verify(h != "localhost");
- return HostAndPort(h, serverGlobalParams.port);
+ if (slash == 0) {
+ return;
}
- void parseReplSetSeedList(ReplicationCoordinatorExternalState* externalState,
- const std::string& replSetString,
- std::string* setname,
- std::vector<HostAndPort>* seeds) {
- const char *p = replSetString.c_str();
- const char *slash = strchr(p, '/');
- std::set<HostAndPort> seedSet;
- if (slash) {
- *setname = string(p, slash-p);
+ p = slash + 1;
+ while (1) {
+ const char* comma = strchr(p, ',');
+ if (comma == 0) {
+ comma = strchr(p, 0);
+ }
+ if (p == comma) {
+ break;
+ }
+ HostAndPort m;
+ try {
+ m = HostAndPort(string(p, comma - p));
+ } catch (...) {
+ uassert(13114, "bad --replSet seed hostname", false);
+ }
+ uassert(13096, "bad --replSet command line config string - dups?", seedSet.count(m) == 0);
+ seedSet.insert(m);
+ // uassert(13101, "can't use localhost in replset host list", !m.isLocalHost());
+ if (externalState->isSelf(m)) {
+ LOG(1) << "ignoring seed " << m.toString() << " (=self)";
+ } else {
+ seeds->push_back(m);
+ }
+ if (*comma == 0) {
+ break;
+ }
+ p = comma + 1;
+ }
+}
+} // namespace
+
+class CmdReplSetInitiate : public ReplSetCommand {
+public:
+ CmdReplSetInitiate() : ReplSetCommand("replSetInitiate") {}
+ virtual void help(stringstream& h) const {
+ h << "Initiate/christen a replica set.";
+ h << "\nhttp://dochub.mongodb.org/core/replicasetcommands";
+ }
+ virtual Status checkAuthForCommand(ClientBasic* client,
+ const std::string& dbname,
+ const BSONObj& cmdObj) {
+ ActionSet actions;
+ actions.addAction(ActionType::replSetConfigure);
+ if (!AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
+ ResourcePattern::forClusterResource(), actions)) {
+ return Status(ErrorCodes::Unauthorized, "Unauthorized");
}
- else {
- *setname = p;
+ return Status::OK();
+ }
+ virtual bool run(OperationContext* txn,
+ const string&,
+ BSONObj& cmdObj,
+ int,
+ string& errmsg,
+ BSONObjBuilder& result) {
+ BSONObj configObj;
+ if (cmdObj["replSetInitiate"].type() == Object) {
+ configObj = cmdObj["replSetInitiate"].Obj();
+ }
+
+ std::string replSetString = getGlobalReplicationCoordinator()->getSettings().replSet;
+ if (replSetString.empty()) {
+ return appendCommandStatus(result,
+ Status(ErrorCodes::NoReplicationEnabled,
+ "This node was not started with the replSet "
+ "option"));
+ }
+
+ if (configObj.isEmpty()) {
+ string noConfigMessage =
+ "no configuration specified. "
+ "Using a default configuration for the set";
+ result.append("info2", noConfigMessage);
+ log() << "initiate : " << noConfigMessage;
+
+ ReplicationCoordinatorExternalStateImpl externalState;
+ std::string name;
+ std::vector<HostAndPort> seeds;
+ parseReplSetSeedList(&externalState, replSetString, &name, &seeds); // may throw...
+
+ BSONObjBuilder b;
+ b.append("_id", name);
+ b.append("version", 1);
+ BSONObjBuilder members;
+ HostAndPort me = someHostAndPortForMe();
+ members.append("0", BSON("_id" << 0 << "host" << me.toString()));
+ result.append("me", me.toString());
+ for (unsigned i = 0; i < seeds.size(); i++) {
+ members.append(BSONObjBuilder::numStr(i + 1),
+ BSON("_id" << i + 1 << "host" << seeds[i].toString()));
+ }
+ b.appendArray("members", members.obj());
+ configObj = b.obj();
+ log() << "created this configuration for initiation : " << configObj.toString();
+ }
+
+ if (configObj.getField("version").eoo()) {
+ // Missing version field defaults to version 1.
+ BSONObjBuilder builder;
+ builder.appendElements(configObj);
+ builder.append("version", 1);
+ configObj = builder.obj();
+ }
+
+ Status status =
+ getGlobalReplicationCoordinator()->processReplSetInitiate(txn, configObj, &result);
+ return appendCommandStatus(result, status);
+ }
+} cmdReplSetInitiate;
+
+class CmdReplSetReconfig : public ReplSetCommand {
+public:
+ virtual void help(stringstream& help) const {
+ help << "Adjust configuration of a replica set\n";
+ help << "{ replSetReconfig : config_object }";
+ help << "\nhttp://dochub.mongodb.org/core/replicasetcommands";
+ }
+ virtual Status checkAuthForCommand(ClientBasic* client,
+ const std::string& dbname,
+ const BSONObj& cmdObj) {
+ ActionSet actions;
+ actions.addAction(ActionType::replSetConfigure);
+ if (!AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
+ ResourcePattern::forClusterResource(), actions)) {
+ return Status(ErrorCodes::Unauthorized, "Unauthorized");
}
-
- if (slash == 0) {
- return;
+ return Status::OK();
+ }
+ CmdReplSetReconfig() : ReplSetCommand("replSetReconfig") {}
+ virtual bool run(OperationContext* txn,
+ const string&,
+ BSONObj& cmdObj,
+ int,
+ string& errmsg,
+ BSONObjBuilder& result) {
+ Status status = getGlobalReplicationCoordinator()->checkReplEnabledForCommand(&result);
+ if (!status.isOK()) {
+ return appendCommandStatus(result, status);
}
- p = slash + 1;
- while (1) {
- const char *comma = strchr(p, ',');
- if (comma == 0) {
- comma = strchr(p,0);
- }
- if (p == comma) {
- break;
- }
- HostAndPort m;
- try {
- m = HostAndPort( string(p, comma-p) );
- }
- catch (...) {
- uassert(13114, "bad --replSet seed hostname", false);
- }
- uassert(13096, "bad --replSet command line config string - dups?",
- seedSet.count(m) == 0);
- seedSet.insert(m);
- //uassert(13101, "can't use localhost in replset host list", !m.isLocalHost());
- if (externalState->isSelf(m)) {
- LOG(1) << "ignoring seed " << m.toString() << " (=self)";
- }
- else {
- seeds->push_back(m);
- }
- if (*comma == 0) {
- break;
- }
- p = comma + 1;
- }
- }
-} // namespace
-
- class CmdReplSetInitiate : public ReplSetCommand {
- public:
- CmdReplSetInitiate() : ReplSetCommand("replSetInitiate") { }
- virtual void help(stringstream& h) const {
- h << "Initiate/christen a replica set.";
- h << "\nhttp://dochub.mongodb.org/core/replicasetcommands";
- }
- virtual Status checkAuthForCommand(ClientBasic* client,
- const std::string& dbname,
- const BSONObj& cmdObj) {
- ActionSet actions;
- actions.addAction(ActionType::replSetConfigure);
- if (!AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
- ResourcePattern::forClusterResource(), actions)) {
- return Status(ErrorCodes::Unauthorized, "Unauthorized");
- }
- return Status::OK();
- }
- virtual bool run(OperationContext* txn,
- const string& ,
- BSONObj& cmdObj,
- int,
- string& errmsg,
- BSONObjBuilder& result) {
-
- BSONObj configObj;
- if( cmdObj["replSetInitiate"].type() == Object ) {
- configObj = cmdObj["replSetInitiate"].Obj();
- }
+ if (cmdObj["replSetReconfig"].type() != Object) {
+ errmsg = "no configuration specified";
+ return false;
+ }
- std::string replSetString = getGlobalReplicationCoordinator()->getSettings().replSet;
- if (replSetString.empty()) {
- return appendCommandStatus(result,
- Status(ErrorCodes::NoReplicationEnabled,
- "This node was not started with the replSet "
- "option"));
- }
+ ReplicationCoordinator::ReplSetReconfigArgs parsedArgs;
+ parsedArgs.newConfigObj = cmdObj["replSetReconfig"].Obj();
+ parsedArgs.force = cmdObj.hasField("force") && cmdObj["force"].trueValue();
+ status =
+ getGlobalReplicationCoordinator()->processReplSetReconfig(txn, parsedArgs, &result);
- if (configObj.isEmpty()) {
- string noConfigMessage = "no configuration specified. "
- "Using a default configuration for the set";
- result.append("info2", noConfigMessage);
- log() << "initiate : " << noConfigMessage;
-
- ReplicationCoordinatorExternalStateImpl externalState;
- std::string name;
- std::vector<HostAndPort> seeds;
- parseReplSetSeedList(
- &externalState,
- replSetString,
- &name,
- &seeds); // may throw...
-
- BSONObjBuilder b;
- b.append("_id", name);
- b.append("version", 1);
- BSONObjBuilder members;
- HostAndPort me = someHostAndPortForMe();
- members.append("0", BSON( "_id" << 0 << "host" << me.toString() ));
- result.append("me", me.toString());
- for( unsigned i = 0; i < seeds.size(); i++ ) {
- members.append(BSONObjBuilder::numStr(i+1),
- BSON( "_id" << i+1 << "host" << seeds[i].toString()));
- }
- b.appendArray("members", members.obj());
- configObj = b.obj();
- log() << "created this configuration for initiation : " <<
- configObj.toString();
- }
+ ScopedTransaction scopedXact(txn, MODE_X);
+ Lock::GlobalWrite globalWrite(txn->lockState());
- if (configObj.getField("version").eoo()) {
- // Missing version field defaults to version 1.
- BSONObjBuilder builder;
- builder.appendElements(configObj);
- builder.append("version", 1);
- configObj = builder.obj();
- }
+ WriteUnitOfWork wuow(txn);
+ if (status.isOK() && !parsedArgs.force) {
+ getGlobalServiceContext()->getOpObserver()->onOpMessage(
+ txn,
+ BSON("msg"
+ << "Reconfig set"
+ << "version" << parsedArgs.newConfigObj["version"]));
+ }
+ wuow.commit();
- Status status = getGlobalReplicationCoordinator()->processReplSetInitiate(txn,
- configObj,
- &result);
- return appendCommandStatus(result, status);
+ return appendCommandStatus(result, status);
+ }
+} cmdReplSetReconfig;
+
+class CmdReplSetFreeze : public ReplSetCommand {
+public:
+ virtual void help(stringstream& help) const {
+ help << "{ replSetFreeze : <seconds> }";
+ help << "'freeze' state of member to the extent we can do that. What this really means is "
+ "that\n";
+ help << "this node will not attempt to become primary until the time period specified "
+ "expires.\n";
+ help << "You can call again with {replSetFreeze:0} to unfreeze sooner.\n";
+ help << "A process restart unfreezes the member also.\n";
+ help << "\nhttp://dochub.mongodb.org/core/replicasetcommands";
+ }
+ virtual Status checkAuthForCommand(ClientBasic* client,
+ const std::string& dbname,
+ const BSONObj& cmdObj) {
+ ActionSet actions;
+ actions.addAction(ActionType::replSetStateChange);
+ if (!AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
+ ResourcePattern::forClusterResource(), actions)) {
+ return Status(ErrorCodes::Unauthorized, "Unauthorized");
}
- } cmdReplSetInitiate;
-
- class CmdReplSetReconfig : public ReplSetCommand {
- public:
- virtual void help( stringstream &help ) const {
- help << "Adjust configuration of a replica set\n";
- help << "{ replSetReconfig : config_object }";
- help << "\nhttp://dochub.mongodb.org/core/replicasetcommands";
- }
- virtual Status checkAuthForCommand(ClientBasic* client,
- const std::string& dbname,
- const BSONObj& cmdObj) {
- ActionSet actions;
- actions.addAction(ActionType::replSetConfigure);
- if (!AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
- ResourcePattern::forClusterResource(), actions)) {
- return Status(ErrorCodes::Unauthorized, "Unauthorized");
- }
- return Status::OK();
- }
- CmdReplSetReconfig() : ReplSetCommand("replSetReconfig") { }
- virtual bool run(OperationContext* txn,
- const string&,
- BSONObj& cmdObj,
- int,
- string& errmsg,
- BSONObjBuilder& result) {
- Status status = getGlobalReplicationCoordinator()->checkReplEnabledForCommand(&result);
- if (!status.isOK()) {
- return appendCommandStatus(result, status);
- }
+ return Status::OK();
+ }
+ CmdReplSetFreeze() : ReplSetCommand("replSetFreeze") {}
+ virtual bool run(OperationContext* txn,
+ const string&,
+ BSONObj& cmdObj,
+ int,
+ string& errmsg,
+ BSONObjBuilder& result) {
+ Status status = getGlobalReplicationCoordinator()->checkReplEnabledForCommand(&result);
+ if (!status.isOK())
+ return appendCommandStatus(result, status);
- if( cmdObj["replSetReconfig"].type() != Object ) {
- errmsg = "no configuration specified";
- return false;
- }
+ int secs = (int)cmdObj.firstElement().numberInt();
+ return appendCommandStatus(
+ result, getGlobalReplicationCoordinator()->processReplSetFreeze(secs, &result));
+ }
+} cmdReplSetFreeze;
+
+class CmdReplSetStepDown : public ReplSetCommand {
+public:
+ virtual void help(stringstream& help) const {
+ help << "{ replSetStepDown : <seconds> }\n";
+ help << "Step down as primary. Will not try to reelect self for the specified time period "
+ "(1 minute if no numeric secs value specified).\n";
+ help << "(If another member with same priority takes over in the meantime, it will stay "
+ "primary.)\n";
+ help << "http://dochub.mongodb.org/core/replicasetcommands";
+ }
+ virtual Status checkAuthForCommand(ClientBasic* client,
+ const std::string& dbname,
+ const BSONObj& cmdObj) {
+ ActionSet actions;
+ actions.addAction(ActionType::replSetStateChange);
+ if (!AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
+ ResourcePattern::forClusterResource(), actions)) {
+ return Status(ErrorCodes::Unauthorized, "Unauthorized");
+ }
+ return Status::OK();
+ }
+ CmdReplSetStepDown() : ReplSetCommand("replSetStepDown") {}
+ virtual bool run(OperationContext* txn,
+ const string&,
+ BSONObj& cmdObj,
+ int,
+ string& errmsg,
+ BSONObjBuilder& result) {
+ Status status = getGlobalReplicationCoordinator()->checkReplEnabledForCommand(&result);
+ if (!status.isOK())
+ return appendCommandStatus(result, status);
- ReplicationCoordinator::ReplSetReconfigArgs parsedArgs;
- parsedArgs.newConfigObj = cmdObj["replSetReconfig"].Obj();
- parsedArgs.force = cmdObj.hasField("force") && cmdObj["force"].trueValue();
- status = getGlobalReplicationCoordinator()->processReplSetReconfig(txn,
- parsedArgs,
- &result);
-
- ScopedTransaction scopedXact(txn, MODE_X);
- Lock::GlobalWrite globalWrite(txn->lockState());
-
- WriteUnitOfWork wuow(txn);
- if (status.isOK() && !parsedArgs.force) {
- getGlobalServiceContext()->getOpObserver()->onOpMessage(
- txn,
- BSON("msg" << "Reconfig set" <<
- "version" << parsedArgs.newConfigObj["version"]));
- }
- wuow.commit();
+ const bool force = cmdObj["force"].trueValue();
+ long long stepDownForSecs = cmdObj.firstElement().numberLong();
+ if (stepDownForSecs == 0) {
+ stepDownForSecs = 60;
+ } else if (stepDownForSecs < 0) {
+ status = Status(ErrorCodes::BadValue, "stepdown period must be a positive integer");
return appendCommandStatus(result, status);
}
- } cmdReplSetReconfig;
-
- class CmdReplSetFreeze : public ReplSetCommand {
- public:
- virtual void help( stringstream &help ) const {
- help << "{ replSetFreeze : <seconds> }";
- help << "'freeze' state of member to the extent we can do that. What this really means is that\n";
- help << "this node will not attempt to become primary until the time period specified expires.\n";
- help << "You can call again with {replSetFreeze:0} to unfreeze sooner.\n";
- help << "A process restart unfreezes the member also.\n";
- help << "\nhttp://dochub.mongodb.org/core/replicasetcommands";
- }
- virtual Status checkAuthForCommand(ClientBasic* client,
- const std::string& dbname,
- const BSONObj& cmdObj) {
- ActionSet actions;
- actions.addAction(ActionType::replSetStateChange);
- if (!AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
- ResourcePattern::forClusterResource(), actions)) {
- return Status(ErrorCodes::Unauthorized, "Unauthorized");
- }
- return Status::OK();
- }
- CmdReplSetFreeze() : ReplSetCommand("replSetFreeze") { }
- virtual bool run(OperationContext* txn,
- const string&,
- BSONObj& cmdObj,
- int,
- string& errmsg,
- BSONObjBuilder& result) {
- Status status = getGlobalReplicationCoordinator()->checkReplEnabledForCommand(&result);
- if (!status.isOK())
- return appendCommandStatus(result, status);
-
- int secs = (int) cmdObj.firstElement().numberInt();
- return appendCommandStatus(
- result,
- getGlobalReplicationCoordinator()->processReplSetFreeze(secs, &result));
- }
- } cmdReplSetFreeze;
-
- class CmdReplSetStepDown: public ReplSetCommand {
- public:
- virtual void help( stringstream &help ) const {
- help << "{ replSetStepDown : <seconds> }\n";
- help << "Step down as primary. Will not try to reelect self for the specified time period (1 minute if no numeric secs value specified).\n";
- help << "(If another member with same priority takes over in the meantime, it will stay primary.)\n";
- help << "http://dochub.mongodb.org/core/replicasetcommands";
- }
- virtual Status checkAuthForCommand(ClientBasic* client,
- const std::string& dbname,
- const BSONObj& cmdObj) {
- ActionSet actions;
- actions.addAction(ActionType::replSetStateChange);
- if (!AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
- ResourcePattern::forClusterResource(), actions)) {
- return Status(ErrorCodes::Unauthorized, "Unauthorized");
- }
- return Status::OK();
- }
- CmdReplSetStepDown() : ReplSetCommand("replSetStepDown") { }
- virtual bool run(OperationContext* txn,
- const string&,
- BSONObj& cmdObj,
- int,
- string& errmsg,
- BSONObjBuilder& result) {
- Status status = getGlobalReplicationCoordinator()->checkReplEnabledForCommand(&result);
- if (!status.isOK())
- return appendCommandStatus(result, status);
-
- const bool force = cmdObj["force"].trueValue();
- long long stepDownForSecs = cmdObj.firstElement().numberLong();
- if (stepDownForSecs == 0) {
- stepDownForSecs = 60;
- }
- else if (stepDownForSecs < 0) {
- status = Status(ErrorCodes::BadValue,
- "stepdown period must be a positive integer");
- return appendCommandStatus(result, status);
- }
-
- long long secondaryCatchUpPeriodSecs;
- status = bsonExtractIntegerField(cmdObj,
- "secondaryCatchUpPeriodSecs",
- &secondaryCatchUpPeriodSecs);
- if (status.code() == ErrorCodes::NoSuchKey) {
- // if field is absent, default values
- if (force) {
- secondaryCatchUpPeriodSecs = 0;
- }
- else {
- secondaryCatchUpPeriodSecs = 10;
- }
- }
- else if (!status.isOK()) {
- return appendCommandStatus(result, status);
- }
-
- if (secondaryCatchUpPeriodSecs < 0) {
- status = Status(ErrorCodes::BadValue,
- "secondaryCatchUpPeriodSecs period must be a positive or absent");
- return appendCommandStatus(result, status);
- }
-
- if (stepDownForSecs < secondaryCatchUpPeriodSecs) {
- status = Status(ErrorCodes::BadValue,
- "stepdown period must be longer than secondaryCatchUpPeriodSecs");
- return appendCommandStatus(result, status);
+ long long secondaryCatchUpPeriodSecs;
+ status = bsonExtractIntegerField(
+ cmdObj, "secondaryCatchUpPeriodSecs", &secondaryCatchUpPeriodSecs);
+ if (status.code() == ErrorCodes::NoSuchKey) {
+ // if field is absent, default values
+ if (force) {
+ secondaryCatchUpPeriodSecs = 0;
+ } else {
+ secondaryCatchUpPeriodSecs = 10;
}
+ } else if (!status.isOK()) {
+ return appendCommandStatus(result, status);
+ }
- log() << "Attempting to step down in response to replSetStepDown command";
+ if (secondaryCatchUpPeriodSecs < 0) {
+ status = Status(ErrorCodes::BadValue,
+ "secondaryCatchUpPeriodSecs period must be a positive or absent");
+ return appendCommandStatus(result, status);
+ }
- status = getGlobalReplicationCoordinator()->stepDown(
- txn,
- force,
- Seconds(secondaryCatchUpPeriodSecs),
- Seconds(stepDownForSecs));
+ if (stepDownForSecs < secondaryCatchUpPeriodSecs) {
+ status = Status(ErrorCodes::BadValue,
+ "stepdown period must be longer than secondaryCatchUpPeriodSecs");
return appendCommandStatus(result, status);
}
- } cmdReplSetStepDown;
-
- class CmdReplSetMaintenance: public ReplSetCommand {
- public:
- virtual void help( stringstream &help ) const {
- help << "{ replSetMaintenance : bool }\n";
- help << "Enable or disable maintenance mode.";
- }
- virtual Status checkAuthForCommand(ClientBasic* client,
- const std::string& dbname,
- const BSONObj& cmdObj) {
- ActionSet actions;
- actions.addAction(ActionType::replSetStateChange);
- if (!AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
- ResourcePattern::forClusterResource(), actions)) {
- return Status(ErrorCodes::Unauthorized, "Unauthorized");
- }
- return Status::OK();
- }
- CmdReplSetMaintenance() : ReplSetCommand("replSetMaintenance") { }
- virtual bool run(OperationContext* txn,
- const string&,
- BSONObj& cmdObj,
- int,
- string& errmsg,
- BSONObjBuilder& result) {
- Status status = getGlobalReplicationCoordinator()->checkReplEnabledForCommand(&result);
- if (!status.isOK())
- return appendCommandStatus(result, status);
- return appendCommandStatus(
- result,
- getGlobalReplicationCoordinator()->setMaintenanceMode(
- cmdObj["replSetMaintenance"].trueValue()));
- }
- } cmdReplSetMaintenance;
-
- class CmdReplSetSyncFrom: public ReplSetCommand {
- public:
- virtual void help( stringstream &help ) const {
- help << "{ replSetSyncFrom : \"host:port\" }\n";
- help << "Change who this member is syncing from.";
- }
- virtual Status checkAuthForCommand(ClientBasic* client,
- const std::string& dbname,
- const BSONObj& cmdObj) {
- ActionSet actions;
- actions.addAction(ActionType::replSetStateChange);
- if (!AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
- ResourcePattern::forClusterResource(), actions)) {
- return Status(ErrorCodes::Unauthorized, "Unauthorized");
- }
- return Status::OK();
- }
- CmdReplSetSyncFrom() : ReplSetCommand("replSetSyncFrom") { }
- virtual bool run(OperationContext* txn,
- const string&,
- BSONObj& cmdObj,
- int,
- string& errmsg,
- BSONObjBuilder& result) {
- Status status = getGlobalReplicationCoordinator()->checkReplEnabledForCommand(&result);
- if (!status.isOK())
- return appendCommandStatus(result, status);
+ log() << "Attempting to step down in response to replSetStepDown command";
- HostAndPort targetHostAndPort;
- status = targetHostAndPort.initialize(cmdObj["replSetSyncFrom"].valuestrsafe());
- if (!status.isOK())
- return appendCommandStatus(result, status);
+ status = getGlobalReplicationCoordinator()->stepDown(
+ txn, force, Seconds(secondaryCatchUpPeriodSecs), Seconds(stepDownForSecs));
+ return appendCommandStatus(result, status);
+ }
+} cmdReplSetStepDown;
- return appendCommandStatus(
- result,
- getGlobalReplicationCoordinator()->processReplSetSyncFrom(targetHostAndPort,
- &result));
- }
- } cmdReplSetSyncFrom;
-
- class CmdReplSetUpdatePosition: public ReplSetCommand {
- public:
- CmdReplSetUpdatePosition() : ReplSetCommand("replSetUpdatePosition") { }
- virtual bool run(OperationContext* txn,
- const string&,
- BSONObj& cmdObj,
- int,
- string& errmsg,
- BSONObjBuilder& result) {
- Status status = getGlobalReplicationCoordinator()->checkReplEnabledForCommand(&result);
- if (!status.isOK())
- return appendCommandStatus(result, status);
+class CmdReplSetMaintenance : public ReplSetCommand {
+public:
+ virtual void help(stringstream& help) const {
+ help << "{ replSetMaintenance : bool }\n";
+ help << "Enable or disable maintenance mode.";
+ }
+ virtual Status checkAuthForCommand(ClientBasic* client,
+ const std::string& dbname,
+ const BSONObj& cmdObj) {
+ ActionSet actions;
+ actions.addAction(ActionType::replSetStateChange);
+ if (!AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
+ ResourcePattern::forClusterResource(), actions)) {
+ return Status(ErrorCodes::Unauthorized, "Unauthorized");
+ }
+ return Status::OK();
+ }
+ CmdReplSetMaintenance() : ReplSetCommand("replSetMaintenance") {}
+ virtual bool run(OperationContext* txn,
+ const string&,
+ BSONObj& cmdObj,
+ int,
+ string& errmsg,
+ BSONObjBuilder& result) {
+ Status status = getGlobalReplicationCoordinator()->checkReplEnabledForCommand(&result);
+ if (!status.isOK())
+ return appendCommandStatus(result, status);
- // accept and ignore handshakes sent from old (3.0-series) nodes without erroring to
- // enable mixed-version operation, since we no longer use the handshakes
- if (cmdObj.hasField("handshake")) {
- return true;
- }
-
- UpdatePositionArgs args;
- status = args.initialize(cmdObj);
- if (!status.isOK())
- return appendCommandStatus(result, status);
+ return appendCommandStatus(result,
+ getGlobalReplicationCoordinator()->setMaintenanceMode(
+ cmdObj["replSetMaintenance"].trueValue()));
+ }
+} cmdReplSetMaintenance;
- // in the case of an update from a member with an invalid replica set config,
- // we return our current config version
- long long configVersion = -1;
- status = getGlobalReplicationCoordinator()->
- processReplSetUpdatePosition(args, &configVersion);
+class CmdReplSetSyncFrom : public ReplSetCommand {
+public:
+ virtual void help(stringstream& help) const {
+ help << "{ replSetSyncFrom : \"host:port\" }\n";
+ help << "Change who this member is syncing from.";
+ }
+ virtual Status checkAuthForCommand(ClientBasic* client,
+ const std::string& dbname,
+ const BSONObj& cmdObj) {
+ ActionSet actions;
+ actions.addAction(ActionType::replSetStateChange);
+ if (!AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
+ ResourcePattern::forClusterResource(), actions)) {
+ return Status(ErrorCodes::Unauthorized, "Unauthorized");
+ }
+ return Status::OK();
+ }
+ CmdReplSetSyncFrom() : ReplSetCommand("replSetSyncFrom") {}
+ virtual bool run(OperationContext* txn,
+ const string&,
+ BSONObj& cmdObj,
+ int,
+ string& errmsg,
+ BSONObjBuilder& result) {
+ Status status = getGlobalReplicationCoordinator()->checkReplEnabledForCommand(&result);
+ if (!status.isOK())
+ return appendCommandStatus(result, status);
- if (status == ErrorCodes::InvalidReplicaSetConfig) {
- result.append("configVersion", configVersion);
- }
+ HostAndPort targetHostAndPort;
+ status = targetHostAndPort.initialize(cmdObj["replSetSyncFrom"].valuestrsafe());
+ if (!status.isOK())
return appendCommandStatus(result, status);
- }
- } cmdReplSetUpdatePosition;
-namespace {
- /**
- * Returns true if there is no data on this server. Useful when starting replication.
- * The "local" database does NOT count except for "rs.oplog" collection.
- * Used to set the hasData field on replset heartbeat command response.
- */
- bool replHasDatabases(OperationContext* txn) {
- std::vector<string> names;
- StorageEngine* storageEngine = getGlobalServiceContext()->getGlobalStorageEngine();
- storageEngine->listDatabases(&names);
-
- if( names.size() >= 2 ) return true;
- if( names.size() == 1 ) {
- if( names[0] != "local" )
- return true;
-
- // we have a local database. return true if oplog isn't empty
- BSONObj o;
- if (Helpers::getSingleton(txn, repl::rsOplogName.c_str(), o)) {
- return true;
- }
- }
- return false;
+ return appendCommandStatus(
+ result,
+ getGlobalReplicationCoordinator()->processReplSetSyncFrom(targetHostAndPort, &result));
}
+} cmdReplSetSyncFrom;
+
+class CmdReplSetUpdatePosition : public ReplSetCommand {
+public:
+ CmdReplSetUpdatePosition() : ReplSetCommand("replSetUpdatePosition") {}
+ virtual bool run(OperationContext* txn,
+ const string&,
+ BSONObj& cmdObj,
+ int,
+ string& errmsg,
+ BSONObjBuilder& result) {
+ Status status = getGlobalReplicationCoordinator()->checkReplEnabledForCommand(&result);
+ if (!status.isOK())
+ return appendCommandStatus(result, status);
-} // namespace
+ // accept and ignore handshakes sent from old (3.0-series) nodes without erroring to
+ // enable mixed-version operation, since we no longer use the handshakes
+ if (cmdObj.hasField("handshake")) {
+ return true;
+ }
- MONGO_FP_DECLARE(rsDelayHeartbeatResponse);
+ UpdatePositionArgs args;
+ status = args.initialize(cmdObj);
+ if (!status.isOK())
+ return appendCommandStatus(result, status);
- /* { replSetHeartbeat : <setname> } */
- class CmdReplSetHeartbeat : public ReplSetCommand {
- public:
- CmdReplSetHeartbeat() : ReplSetCommand("replSetHeartbeat") { }
- virtual bool run(OperationContext* txn,
- const string&,
- BSONObj& cmdObj,
- int,
- string& errmsg,
- BSONObjBuilder& result) {
+ // in the case of an update from a member with an invalid replica set config,
+ // we return our current config version
+ long long configVersion = -1;
+ status =
+ getGlobalReplicationCoordinator()->processReplSetUpdatePosition(args, &configVersion);
- MONGO_FAIL_POINT_BLOCK(rsDelayHeartbeatResponse, delay) {
- const BSONObj& data = delay.getData();
- sleepsecs(data["delay"].numberInt());
- }
+ if (status == ErrorCodes::InvalidReplicaSetConfig) {
+ result.append("configVersion", configVersion);
+ }
+ return appendCommandStatus(result, status);
+ }
+} cmdReplSetUpdatePosition;
- Status status = Status(ErrorCodes::InternalError, "status not set in heartbeat code");
- /* we don't call ReplSetCommand::check() here because heartbeat
- checks many things that are pre-initialization. */
- if (!getGlobalReplicationCoordinator()->getSettings().usingReplSets()) {
- status = Status(ErrorCodes::NoReplicationEnabled, "not running with --replSet");
- return appendCommandStatus(result, status);
- }
+namespace {
+/**
+ * Returns true if there is no data on this server. Useful when starting replication.
+ * The "local" database does NOT count except for "rs.oplog" collection.
+ * Used to set the hasData field on replset heartbeat command response.
+ */
+bool replHasDatabases(OperationContext* txn) {
+ std::vector<string> names;
+ StorageEngine* storageEngine = getGlobalServiceContext()->getGlobalStorageEngine();
+ storageEngine->listDatabases(&names);
+
+ if (names.size() >= 2)
+ return true;
+ if (names.size() == 1) {
+ if (names[0] != "local")
+ return true;
- /* we want to keep heartbeat connections open when relinquishing primary.
- tag them here. */
- {
- AbstractMessagingPort *mp = txn->getClient()->port();
- if( mp )
- mp->tag |= executor::NetworkInterface::kMessagingPortKeepOpen;
- }
+ // we have a local database. return true if oplog isn't empty
+ BSONObj o;
+ if (Helpers::getSingleton(txn, repl::rsOplogName.c_str(), o)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace
+
+MONGO_FP_DECLARE(rsDelayHeartbeatResponse);
+
+/* { replSetHeartbeat : <setname> } */
+class CmdReplSetHeartbeat : public ReplSetCommand {
+public:
+ CmdReplSetHeartbeat() : ReplSetCommand("replSetHeartbeat") {}
+ virtual bool run(OperationContext* txn,
+ const string&,
+ BSONObj& cmdObj,
+ int,
+ string& errmsg,
+ BSONObjBuilder& result) {
+ MONGO_FAIL_POINT_BLOCK(rsDelayHeartbeatResponse, delay) {
+ const BSONObj& data = delay.getData();
+ sleepsecs(data["delay"].numberInt());
+ }
+
+ Status status = Status(ErrorCodes::InternalError, "status not set in heartbeat code");
+ /* we don't call ReplSetCommand::check() here because heartbeat
+ checks many things that are pre-initialization. */
+ if (!getGlobalReplicationCoordinator()->getSettings().usingReplSets()) {
+ status = Status(ErrorCodes::NoReplicationEnabled, "not running with --replSet");
+ return appendCommandStatus(result, status);
+ }
- if (getGlobalReplicationCoordinator()->isV1ElectionProtocol()) {
- ReplSetHeartbeatArgsV1 args;
- status = args.initialize(cmdObj);
- if (status.isOK()) {
- ReplSetHeartbeatResponse response;
- status = getGlobalReplicationCoordinator()->processHeartbeatV1(args, &response);
- if (status.isOK())
- response.addToBSON(&result, true);
- return appendCommandStatus(result, status);
- }
- // else: fall through to old heartbeat protocol as it is likely that
- // a new node just joined the set
- }
+ /* we want to keep heartbeat connections open when relinquishing primary.
+ tag them here. */
+ {
+ AbstractMessagingPort* mp = txn->getClient()->port();
+ if (mp)
+ mp->tag |= executor::NetworkInterface::kMessagingPortKeepOpen;
+ }
- ReplSetHeartbeatArgs args;
+ if (getGlobalReplicationCoordinator()->isV1ElectionProtocol()) {
+ ReplSetHeartbeatArgsV1 args;
status = args.initialize(cmdObj);
- if (!status.isOK()) {
+ if (status.isOK()) {
+ ReplSetHeartbeatResponse response;
+ status = getGlobalReplicationCoordinator()->processHeartbeatV1(args, &response);
+ if (status.isOK())
+ response.addToBSON(&result, true);
return appendCommandStatus(result, status);
}
+ // else: fall through to old heartbeat protocol as it is likely that
+ // a new node just joined the set
+ }
- // ugh.
- if (args.getCheckEmpty()) {
- result.append("hasData", replHasDatabases(txn));
- }
-
- ReplSetHeartbeatResponse response;
- status = getGlobalReplicationCoordinator()->processHeartbeat(args, &response);
- if (status.isOK())
- response.addToBSON(&result, false);
+ ReplSetHeartbeatArgs args;
+ status = args.initialize(cmdObj);
+ if (!status.isOK()) {
return appendCommandStatus(result, status);
}
- } cmdReplSetHeartbeat;
-
- /** the first cmd called by a node seeking election and it's a basic sanity
- test: do any of the nodes it can reach know that it can't be the primary?
- */
- class CmdReplSetFresh : public ReplSetCommand {
- public:
- CmdReplSetFresh() : ReplSetCommand("replSetFresh") { }
-
- virtual bool run(OperationContext* txn,
- const string&,
- BSONObj& cmdObj,
- int,
- string& errmsg,
- BSONObjBuilder& result) {
- Status status = getGlobalReplicationCoordinator()->checkReplEnabledForCommand(&result);
- if (!status.isOK())
- return appendCommandStatus(result, status);
- ReplicationCoordinator::ReplSetFreshArgs parsedArgs;
- parsedArgs.id = cmdObj["id"].Int();
- parsedArgs.setName = cmdObj["set"].String();
- parsedArgs.who = HostAndPort(cmdObj["who"].String());
- BSONElement cfgverElement = cmdObj["cfgver"];
- uassert(28525,
- str::stream() << "Expected cfgver argument to replSetFresh command to have "
- "numeric type, but found " << typeName(cfgverElement.type()),
- cfgverElement.isNumber());
- parsedArgs.cfgver = cfgverElement.safeNumberLong();
- parsedArgs.opTime = Timestamp(cmdObj["opTime"].Date());
-
- status = getGlobalReplicationCoordinator()->processReplSetFresh(parsedArgs, &result);
- return appendCommandStatus(result, status);
+ // ugh.
+ if (args.getCheckEmpty()) {
+ result.append("hasData", replHasDatabases(txn));
}
- } cmdReplSetFresh;
-
- class CmdReplSetElect : public ReplSetCommand {
- public:
- CmdReplSetElect() : ReplSetCommand("replSetElect") { }
- private:
- virtual bool run(OperationContext* txn,
- const string&,
- BSONObj& cmdObj,
- int,
- string& errmsg,
- BSONObjBuilder& result) {
- DEV log() << "received elect msg " << cmdObj.toString();
- else LOG(2) << "received elect msg " << cmdObj.toString();
-
- Status status = getGlobalReplicationCoordinator()->checkReplEnabledForCommand(&result);
- if (!status.isOK())
- return appendCommandStatus(result, status);
- ReplicationCoordinator::ReplSetElectArgs parsedArgs;
- parsedArgs.set = cmdObj["set"].String();
- parsedArgs.whoid = cmdObj["whoid"].Int();
- BSONElement cfgverElement = cmdObj["cfgver"];
- uassert(28526,
- str::stream() << "Expected cfgver argument to replSetElect command to have "
- "numeric type, but found " << typeName(cfgverElement.type()),
- cfgverElement.isNumber());
- parsedArgs.cfgver = cfgverElement.safeNumberLong();
- parsedArgs.round = cmdObj["round"].OID();
-
- status = getGlobalReplicationCoordinator()->processReplSetElect(parsedArgs, &result);
+ ReplSetHeartbeatResponse response;
+ status = getGlobalReplicationCoordinator()->processHeartbeat(args, &response);
+ if (status.isOK())
+ response.addToBSON(&result, false);
+ return appendCommandStatus(result, status);
+ }
+} cmdReplSetHeartbeat;
+
+/** the first cmd called by a node seeking election and it's a basic sanity
+ test: do any of the nodes it can reach know that it can't be the primary?
+ */
+class CmdReplSetFresh : public ReplSetCommand {
+public:
+ CmdReplSetFresh() : ReplSetCommand("replSetFresh") {}
+
+ virtual bool run(OperationContext* txn,
+ const string&,
+ BSONObj& cmdObj,
+ int,
+ string& errmsg,
+ BSONObjBuilder& result) {
+ Status status = getGlobalReplicationCoordinator()->checkReplEnabledForCommand(&result);
+ if (!status.isOK())
return appendCommandStatus(result, status);
- }
- } cmdReplSetElect;
-} // namespace repl
-} // namespace mongo
+ ReplicationCoordinator::ReplSetFreshArgs parsedArgs;
+ parsedArgs.id = cmdObj["id"].Int();
+ parsedArgs.setName = cmdObj["set"].String();
+ parsedArgs.who = HostAndPort(cmdObj["who"].String());
+ BSONElement cfgverElement = cmdObj["cfgver"];
+ uassert(28525,
+ str::stream() << "Expected cfgver argument to replSetFresh command to have "
+ "numeric type, but found " << typeName(cfgverElement.type()),
+ cfgverElement.isNumber());
+ parsedArgs.cfgver = cfgverElement.safeNumberLong();
+ parsedArgs.opTime = Timestamp(cmdObj["opTime"].Date());
+
+ status = getGlobalReplicationCoordinator()->processReplSetFresh(parsedArgs, &result);
+ return appendCommandStatus(result, status);
+ }
+} cmdReplSetFresh;
+
+class CmdReplSetElect : public ReplSetCommand {
+public:
+ CmdReplSetElect() : ReplSetCommand("replSetElect") {}
+
+private:
+ virtual bool run(OperationContext* txn,
+ const string&,
+ BSONObj& cmdObj,
+ int,
+ string& errmsg,
+ BSONObjBuilder& result) {
+ DEV log() << "received elect msg " << cmdObj.toString();
+ else LOG(2) << "received elect msg " << cmdObj.toString();
+
+ Status status = getGlobalReplicationCoordinator()->checkReplEnabledForCommand(&result);
+ if (!status.isOK())
+ return appendCommandStatus(result, status);
+
+ ReplicationCoordinator::ReplSetElectArgs parsedArgs;
+ parsedArgs.set = cmdObj["set"].String();
+ parsedArgs.whoid = cmdObj["whoid"].Int();
+ BSONElement cfgverElement = cmdObj["cfgver"];
+ uassert(28526,
+ str::stream() << "Expected cfgver argument to replSetElect command to have "
+ "numeric type, but found " << typeName(cfgverElement.type()),
+ cfgverElement.isNumber());
+ parsedArgs.cfgver = cfgverElement.safeNumberLong();
+ parsedArgs.round = cmdObj["round"].OID();
+
+ status = getGlobalReplicationCoordinator()->processReplSetElect(parsedArgs, &result);
+ return appendCommandStatus(result, status);
+ }
+} cmdReplSetElect;
+
+} // namespace repl
+} // namespace mongo