@@ -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
0 commit comments