-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathacceptor.go
117 lines (99 loc) · 2.63 KB
/
acceptor.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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package paxos
import (
"fmt"
"time"
)
type slotState struct {
slot int
highestProposalNumber int
acceptedProposalNumber *int
acceptedValue *int
}
type Acceptor struct {
ID int
ProposerInput *Channel
Proposers map[int]*Channel
Learners map[int]*Channel
state map[int]*slotState
}
func (a *Acceptor) Run() {
for {
msg := <-a.ProposerInput.Read()
if msg.Prepare != nil {
a.handlePrepare(*msg.Prepare)
} else if msg.Accept != nil {
a.handleAccept(*msg.Accept)
} else {
fmt.Printf("Acceptor %v received a message without any content from proposer", a.ID)
}
time.Sleep(loopWaitTime)
}
}
func (a *Acceptor) handlePrepare(msg PrepareMsg) {
if _, ok := a.state[msg.Slot]; !ok {
a.state[msg.Slot] = &slotState{
slot: msg.Slot,
highestProposalNumber: -1,
}
}
state := a.state[msg.Slot]
if state.highestProposalNumber >= msg.ProposalNumber {
return
}
state.highestProposalNumber = msg.ProposalNumber
maxAcceptedSlot := -1
for slot, st := range a.state {
if st.acceptedValue == nil {
continue
}
if slot > maxAcceptedSlot {
maxAcceptedSlot = slot
}
}
out := PromiseMsg{
Slot: state.slot,
ProposerID: msg.ProposerID,
AcceptorID: a.ID,
AcceptedProposalNumber: state.acceptedProposalNumber,
AcceptedValue: state.acceptedValue,
HighestAcceptedSlot: maxAcceptedSlot,
}
a.Proposers[msg.ProposerID].Write() <- Msg{Promise: &out}
}
func (a *Acceptor) handleAccept(msg AcceptMsg) {
// TODO(rithvikp): Should this situation be an error instead?
if _, ok := a.state[msg.Slot]; !ok {
a.state[msg.Slot] = &slotState{
slot: msg.Slot,
highestProposalNumber: -1,
}
}
state := a.state[msg.Slot]
if state.highestProposalNumber > msg.ProposalNumber {
return
}
// TODO(rithvikp): Should there be an error if this value is different from a previously accepted value?
state.acceptedProposalNumber = &msg.ProposalNumber
state.acceptedValue = &msg.Value
for pID, ch := range a.Proposers {
out := AcceptedMsg{
Slot: state.slot,
ProposerID: pID,
AcceptorID: a.ID,
ProposalNumber: msg.ProposalNumber,
Value: msg.Value,
}
ch.Write() <- Msg{Accepted: &out}
}
for lID, ch := range a.Learners {
out := LearnMsg{
Slot: state.slot,
AcceptorID: a.ID,
LearnerID: lID,
Value: msg.Value,
}
ch.Write() <- Msg{Learn: &out}
}
fmt.Printf("[ACCEPTOR] Accepted a value for slot %d --> Proposer: %v, Acceptor: %v, Proposal #: %d, Value: %v\n",
state.slot, msg.ProposerID, a.ID, msg.ProposalNumber, msg.Value)
}