changeset 22:95173b9adfc7

Increase safety for elections: Step down if instance is too low
author Lewin Bormann <lbo@spheniscida.de>
date Sat, 08 Oct 2016 16:33:42 +0200
parents 33f31940385e
children fdd258eb58bc
files consensus.go
diffstat 1 files changed, 6 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/consensus.go	Sat Oct 08 14:12:06 2016 +0200
+++ b/consensus.go	Sat Oct 08 16:33:42 2016 +0200
@@ -95,8 +95,11 @@
 			errs = append(errs, NewError(ERR_CALL, "Error from remote participant", err))
 
 			// force: re-send snapshot if the client has seen a gap
+
+			// Useful to solve generic network errors
 			p.forceReconnect(member)
 
+			// Especially useful to solve ERR_STATE, ERR_GAP errors
 			client.StartParticipation(p.instance, p.sequence, p.cluster, member, p.self, p.members, p.state.Snapshot())
 
 			ok, err := client.Accept(p.instance, p.sequence+1, c)
@@ -197,9 +200,8 @@
 			errs = append(errs, NewError(ERR_CALL, fmt.Sprintf("Error calling Prepare() on %v", member), err))
 			continue
 		}
-		if newInstance != p.instance+1 {
-			errs = append(errs, NewError(ERR_DENIED, fmt.Sprintf("Vote denied; proposal %d, response %d", p.instance+1, newInstance), nil))
-			continue
+		if newInstance > p.instance+1 {
+			return NewError(ERR_DENIED, fmt.Sprintf("We don't have an up-to-date local state (instance %d/%d)", p.instance+1, newInstance), nil)
 		}
 
 		acquiredVotes++
@@ -211,6 +213,7 @@
 	}
 
 	p.instance++
+	p.sequence = 0
 	p.participantState = state_MASTER
 	return nil
 }