Skip to content

Commit 4f43fb1

Browse files
SERVER-14033: implement prepareElectCmdResponse in topology coordinator
1 parent b6b40f6 commit 4f43fb1

File tree

2 files changed

+83
-0
lines changed

2 files changed

+83
-0
lines changed

src/mongo/db/repl/topology_coordinator_impl.cpp

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,10 +323,86 @@ namespace repl {
323323
return false;
324324
}
325325

326+
namespace {
327+
const size_t LeaseTime = 3;
328+
} // namespace
329+
326330
// produce a reply to a received electCmd
327331
void TopologyCoordinatorImpl::prepareElectCmdResponse(const Date_t now,
328332
const BSONObj& cmdObj,
329333
BSONObjBuilder& result) {
334+
335+
//TODO: after eric's checkin, add executer stuff and error if cancelled
336+
DEV log() << "replSet received elect msg " << cmdObj.toString() << rsLog;
337+
else LOG(2) << "replSet received elect msg " << cmdObj.toString() << rsLog;
338+
339+
string setName = cmdObj["setName"].String();
340+
unsigned whoid = cmdObj["whoid"].Int();
341+
int cfgver = cmdObj["cfgver"].Int();
342+
OID round = cmdObj["round"].OID();
343+
int myver = _currentConfig.version;
344+
345+
const Member* primary = _currentPrimary;
346+
const Member* hopeful = _getConstMember(whoid);
347+
const Member* highestPriority = _getHighestPriorityElectable();
348+
349+
int vote = 0;
350+
if( setName != _currentConfig.replSetName ) {
351+
log() << "replSet error received an elect request for '" << setName
352+
<< "' but our setName name is '" << _currentConfig.replSetName << "'" << rsLog;
353+
}
354+
else if( myver < cfgver ) {
355+
// we are stale. don't vote
356+
}
357+
else if( myver > cfgver ) {
358+
// they are stale!
359+
log() << "replSet electCmdReceived info got stale version # during election" << rsLog;
360+
vote = -10000;
361+
}
362+
else if( !hopeful ) {
363+
log() << "replSet electCmdReceived couldn't find member with id " << whoid << rsLog;
364+
vote = -10000;
365+
}
366+
else if( primary && _memberState == MemberState::RS_PRIMARY ) {
367+
log() << "I am already primary, " << hopeful->fullName()
368+
<< " can try again once I've stepped down" << rsLog;
369+
vote = -10000;
370+
}
371+
else if (primary) {
372+
log() << hopeful->fullName() << " is trying to elect itself but " <<
373+
primary->fullName() << " is already primary" << rsLog;
374+
vote = -10000;
375+
}
376+
else if( highestPriority &&
377+
highestPriority->config().priority > hopeful->config().priority) {
378+
log() << hopeful->fullName() << " has lower priority than "
379+
<< highestPriority->fullName();
380+
vote = -10000;
381+
}
382+
else {
383+
try {
384+
if( _lastVote.when + LeaseTime >= now && _lastVote.who != whoid ) {
385+
LOG(1) << "replSet not voting yea for " << whoid
386+
<< " voted for " << _lastVote.who << ' ' << now-_lastVote.when
387+
<< " secs ago" << rsLog;
388+
//TODO: remove exception, and change control flow?
389+
throw VoteException();
390+
}
391+
_lastVote.when = now;
392+
_lastVote.who = whoid;
393+
vote = _currentConfig.self->votes;
394+
dassert( hopeful->id() == whoid );
395+
log() << "replSet info voting yea for " << hopeful->fullName()
396+
<< " (" << whoid << ')' << rsLog;
397+
}
398+
catch(VoteException&) {
399+
log() << "replSet voting no for " << hopeful->fullName()
400+
<< " already voted for another" << rsLog;
401+
}
402+
}
403+
404+
result.append("vote", vote);
405+
result.append("round", round);
330406
}
331407

332408
// produce a reply to a heartbeat

src/mongo/db/repl/topology_coordinator_impl.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,13 @@ namespace repl {
214214
}
215215
} _heartbeatOptions;
216216

217+
// Last vote info from the election
218+
struct LastVote {
219+
LastVote() : when(0), who(0xffffffff) { }
220+
Date_t when;
221+
unsigned who;
222+
} _lastVote;
223+
217224

218225
};
219226

0 commit comments

Comments
 (0)