forked from hashicorp/raft
/
verifier.go
74 lines (65 loc) · 2.08 KB
/
verifier.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package fuzzy
import (
"fmt"
"sync"
"testing"
"github.com/hashicorp/raft"
)
// AppendEntriesVerifier looks at all the AppendEntry RPC request and verifies that only one node sends AE requests for any given term
// it also verifies that the request only comes from the node indicated as the leader in the AE message.
type appendEntriesVerifier struct {
sync.RWMutex
leaderForTerm map[uint64]string
errors []string
}
func (v *appendEntriesVerifier) Report(t *testing.T) {
v.Lock()
defer v.Unlock()
for _, e := range v.errors {
t.Error(e)
}
}
func (v *appendEntriesVerifier) Init() {
v.Lock()
defer v.Unlock()
v.leaderForTerm = make(map[uint64]string)
v.errors = make([]string, 0, 10)
}
func (v *appendEntriesVerifier) PreRPC(src, target string, r *raft.RPC) error {
return nil
}
func (v *appendEntriesVerifier) PostRPC(src, target string, req *raft.RPC, res *raft.RPCResponse) error {
return nil
}
func (v *appendEntriesVerifier) PreRequestVote(src, target string, rv *raft.RequestVoteRequest) (*raft.RequestVoteResponse, error) {
return nil, nil
}
func (v *appendEntriesVerifier) PreAppendEntries(src, target string, req *raft.AppendEntriesRequest) (*raft.AppendEntriesResponse, error) {
term := req.Term
ldr := string(req.Leader)
if ldr != src {
v.Lock()
defer v.Unlock()
v.errors = append(v.errors, fmt.Sprintf("Node %v sent an appendEnties request for term %d that said the leader was some other node %v", src, term, ldr))
}
v.RLock()
tl, exists := v.leaderForTerm[term]
v.RUnlock()
if exists && tl != ldr {
v.Lock()
defer v.Unlock()
v.errors = append(v.errors, fmt.Sprintf("Node %v sent an AppendEntries request for term %d, but node %v had already done some, multiple leaders for same term!", src, term, tl))
}
if !exists {
v.Lock()
tl, exists := v.leaderForTerm[term]
if exists && tl != ldr {
v.errors = append(v.errors, fmt.Sprintf("Node %v sent an AppendEntries request for term %d, but node %v had already done some, multiple leaders for same term!", src, term, tl))
}
if !exists {
v.leaderForTerm[term] = ldr
}
v.Unlock()
}
return nil, nil
}