diff options
Diffstat (limited to 'db/repl/rs_initiate.cpp')
-rw-r--r-- | db/repl/rs_initiate.cpp | 41 |
1 files changed, 27 insertions, 14 deletions
diff --git a/db/repl/rs_initiate.cpp b/db/repl/rs_initiate.cpp index cf1941f..3d998a8 100644 --- a/db/repl/rs_initiate.cpp +++ b/db/repl/rs_initiate.cpp @@ -37,8 +37,8 @@ namespace mongo { throws @param initial true when initiating */ - void checkMembersUpForConfigChange(const ReplSetConfig& cfg, bool initial) { - int failures = 0; + void checkMembersUpForConfigChange(const ReplSetConfig& cfg, BSONObjBuilder& result, bool initial) { + int failures = 0, allVotes = 0, allowableFailures = 0; int me = 0; stringstream selfs; for( vector<ReplSetConfig::MemberCfg>::const_iterator i = cfg.members.begin(); i != cfg.members.end(); i++ ) { @@ -51,7 +51,10 @@ namespace mongo { uasserted(13420, "initiation and reconfiguration of a replica set must be sent to a node that can become primary"); } } + allVotes += i->votes; } + allowableFailures = allVotes - (allVotes/2 + 1); + uassert(13278, "bad config: isSelf is true for multiple hosts: " + selfs.str(), me <= 1); // dups? if( me != 1 ) { stringstream ss; @@ -61,6 +64,7 @@ namespace mongo { uasserted(13279, ss.str()); } + vector<string> down; for( vector<ReplSetConfig::MemberCfg>::const_iterator i = cfg.members.begin(); i != cfg.members.end(); i++ ) { // we know we're up if (i->h.isSelf()) { @@ -100,27 +104,27 @@ namespace mongo { } } if( !ok && !res["rs"].trueValue() ) { + down.push_back(i->h.toString()); + if( !res.isEmpty() ) { /* strange. got a response, but not "ok". log it. */ log() << "replSet warning " << i->h.toString() << " replied: " << res.toString() << rsLog; } bool allowFailure = false; - failures++; - if( res.isEmpty() && !initial && failures == 1 ) { - /* for now we are only allowing 1 node to be down on a reconfig. this can be made to be a minority - trying to keep change small as release is near. - */ + failures += i->votes; + if( !initial && failures <= allowableFailures ) { const Member* m = theReplSet->findById( i->_id ); if( m ) { - // ok, so this was an existing member (wouldn't make sense to add to config a new member that is down) assert( m->h().toString() == i->h.toString() ); - allowFailure = true; } + // it's okay if the down member isn't part of the config, + // we might be adding a new member that isn't up yet + allowFailure = true; } if( !allowFailure ) { - string msg = string("need members up to initiate, not ok : ") + i->h.toString(); + string msg = string("need all members up to initiate, not ok : ") + i->h.toString(); if( !initial ) msg = string("need most members up to reconfigure, not ok : ") + i->h.toString(); uasserted(13144, msg); @@ -133,6 +137,9 @@ namespace mongo { !hasData || i->h.isSelf()); } } + if (down.size() > 0) { + result.append("down", down); + } } class CmdReplSetInitiate : public ReplSetCommand { @@ -143,7 +150,7 @@ namespace mongo { h << "Initiate/christen a replica set."; h << "\nhttp://www.mongodb.org/display/DOCS/Replica+Set+Commands"; } - virtual bool run(const string& , BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl) { + virtual bool run(const string& , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) { log() << "replSet replSetInitiate admin command received from client" << rsLog; if( !replSet ) { @@ -179,7 +186,7 @@ namespace mongo { if( ReplSet::startupStatus == ReplSet::BADCONFIG ) { errmsg = "server already in BADCONFIG state (check logs); not initiating"; - result.append("info", ReplSet::startupStatusMsg); + result.append("info", ReplSet::startupStatusMsg.get()); return false; } if( ReplSet::startupStatus != ReplSet::EMPTYCONFIG ) { @@ -204,6 +211,7 @@ namespace mongo { b.append("_id", name); bob members; members.append("0", BSON( "_id" << 0 << "host" << HostAndPort::Me().toString() )); + result.append("me", HostAndPort::Me().toString()); for( unsigned i = 0; i < seeds.size(); i++ ) members.append(bob::numStr(i+1), BSON( "_id" << i+1 << "host" << seeds[i].toString())); b.appendArray("members", members.obj()); @@ -226,7 +234,7 @@ namespace mongo { log() << "replSet replSetInitiate config object parses ok, " << newConfig.members.size() << " members specified" << rsLog; - checkMembersUpForConfigChange(newConfig, true); + checkMembersUpForConfigChange(newConfig, result, true); log() << "replSet replSetInitiate all members seem up" << rsLog; @@ -238,7 +246,7 @@ namespace mongo { log() << "replSet replSetInitiate config now saved locally. Should come online in about a minute." << rsLog; result.append("info", "Config now saved locally. Should come online in about a minute."); ReplSet::startupStatus = ReplSet::SOON; - ReplSet::startupStatusMsg = "Received replSetInitiate - should come online shortly."; + ReplSet::startupStatusMsg.set("Received replSetInitiate - should come online shortly."); } catch( DBException& e ) { log() << "replSet replSetInitiate exception: " << e.what() << rsLog; @@ -248,6 +256,11 @@ namespace mongo { errmsg = string("couldn't initiate : ") + e.what(); return false; } + catch( string& e2 ) { + log() << e2 << rsLog; + errmsg = e2; + return false; + } return true; } |