From 803c4e15142f55445b7806a829139115d64cee9a Mon Sep 17 00:00:00 2001 From: Dwight Merriman Date: Sat, 15 May 2010 18:20:55 -0400 Subject: [PATCH] rs --- db/repl/consensus.cpp | 23 ++++++++++--- db/repl/manager.cpp | 80 +++++++++++++++++++++---------------------- db/repl/replset.h | 13 +++---- 3 files changed, 66 insertions(+), 50 deletions(-) diff --git a/db/repl/consensus.cpp b/db/repl/consensus.cpp index da782dd5191..adfddc5f2de 100644 --- a/db/repl/consensus.cpp +++ b/db/repl/consensus.cpp @@ -64,7 +64,7 @@ namespace mongo { static const int VETO = -10000; - bool ReplSet::Consensus::electSelf() { + void ReplSet::Consensus::_electSelf() { ReplSet::Member& me = *rs._self; electCmd = BSON( "replSetElect" << 1 << @@ -96,11 +96,26 @@ namespace mongo { if( time(0) - start > 30 ) { // defensive; should never happen as we have timeouts on connection and operation for our conn log() << "replSet too much time passed during election, ignoring result" << rsLog; - return false; } - return true; + /* succeeded. */ + rs._myState = PRIMARY; + log() << "replSet elected self as primary" << rsLog; + return; } - return false; + } + + void ReplSet::Consensus::electSelf() { + static mutex m; + { + scoped_lock lk(m); + if( inprog ) return; + inprog = true; + } + try { _electSelf(); } catch(...) { } + { + scoped_lock lk(m); + inprog = false; + } } } diff --git a/db/repl/manager.cpp b/db/repl/manager.cpp index c5ec2f700c7..cbbbc2c0c22 100644 --- a/db/repl/manager.cpp +++ b/db/repl/manager.cpp @@ -53,51 +53,51 @@ namespace mongo { /** called as the health threads get new results */ void ReplSet::Manager::checkNewState() { static mutex m; - scoped_lock lk(m); + { + scoped_lock lk(m); - //log() << "replSet checkNewState " << rsLog; - - const Member *p = _rs->currentPrimary(); - const Member *p2 = findOtherPrimary(); - try { p2 = findOtherPrimary(); } - catch(string s) { - log() << "replSet warning DIAG TODO " << s << rsLog; - return; - } - - if( p == p2 && p ) return; - - if( p2 ) { - /* someone else thinks they are primary. */ - if( p == p2 ) + const Member *p = _rs->currentPrimary(); + const Member *p2 = findOtherPrimary(); + try { p2 = findOtherPrimary(); } + catch(string s) { + /* two other nodes think they are primary (asynchronously polled) -- wait for things to settle down. */ + log() << "replSet warning DIAG TODO " << s << rsLog; return; - if( p == 0 ) - noteARemoteIsPrimary(p2); return; - if( p != _rs->_self ) - noteARemoteIsPrimary(p2); return; - /* we thought we were primary, yet now someone else thinks they are. */ - if( !_rs->elect.aMajoritySeemsToBeUp() ) - noteARemoteIsPrimary(p2); return; - /* ignore for now, keep thinking we are master */ - return; - } + } - if( p ) { - /* we are already primary, and nothing significant out there has changed. */\ - /* todo: if !aMajoritySeemsToBeUp, relinquish */ - assert( p == _rs->_self ); - return; - } + if( p == p2 && p ) return; - /* no one seems to be primary. shall we try to elect ourself? */ - if( !_rs->elect.aMajoritySeemsToBeUp() ) { - _rs->_self->_lastHeartbeatErrMsg.set("can't see a majority, won't elect self"); - return; - } + if( p2 ) { + /* someone else thinks they are primary. */ + if( p == p2 ) // already match + return; + if( p == 0 ) + noteARemoteIsPrimary(p2); return; + if( p != _rs->_self ) + noteARemoteIsPrimary(p2); return; + /* we thought we were primary, yet now someone else thinks they are. */ + if( !_rs->elect.aMajoritySeemsToBeUp() ) + noteARemoteIsPrimary(p2); return; + /* ignore for now, keep thinking we are master */ + return; + } - log() << "replSet todo elect self as primary primary" << rsLog; - _rs->_self->_lastHeartbeatErrMsg.set("todo code #2"); + if( p ) { + /* we are already primary, and nothing significant out there has changed. */ + /* todo: if !aMajoritySeemsToBeUp, relinquish */ + assert( p == _rs->_self ); + return; + } + + /* no one seems to be primary. shall we try to elect ourself? */ + if( !_rs->elect.aMajoritySeemsToBeUp() ) { + _rs->_self->_lastHeartbeatErrMsg.set("can't see a majority, won't elect self"); + return; + } + + _rs->_self->_lastHeartbeatErrMsg.set(""); + } + _rs->elect.electSelf(); } - } diff --git a/db/repl/replset.h b/db/repl/replset.h index 077aafb6653..28fe9f9030b 100644 --- a/db/repl/replset.h +++ b/db/repl/replset.h @@ -54,7 +54,6 @@ namespace mongo { State _myState; public: - void fatal(); bool isMaster(const char *client); void fillIsMaster(BSONObjBuilder&); @@ -66,8 +65,7 @@ namespace mongo { replsetname/host1,host2:port,... where :port is optional. - throws exception if a problem initializing. - */ + throws exception if a problem initializing. */ ReplSet(string cfgString); /* call after constructing to start - returns fairly quickly after launching its threads */ @@ -90,12 +88,15 @@ namespace mongo { void loadConfig(); void initFromConfig(ReplSetConfig& c);//, bool save); - struct Consensus { + class Consensus { ReplSet &rs; - Consensus(ReplSet *t) : rs(*t) { } + bool inprog; + void _electSelf(); + public: + Consensus(ReplSet *t) : rs(*t),inprog(false) { } int totalVotes() const; bool aMajoritySeemsToBeUp() const; - bool electSelf(); + void electSelf(); } elect; public: