-
Notifications
You must be signed in to change notification settings - Fork 6
/
acceptor.go
80 lines (73 loc) · 2.33 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
package paxos
import "log"
//Create a accetor and also assign learning IDs into acceptor.
//Acceptor: Will response request from proposer, promise the first and largest seq number propose.
// After proposer reach the majority promise. Acceptor will pass the proposal value to learner to confirn and choose.
func NewAcceptor(id int, nt nodeNetwork, learners ...int) acceptor {
newAccptor := acceptor{id: id, nt: nt}
newAccptor.learners = learners
return newAccptor
}
type acceptor struct {
id int
learners []int
acceptMsg message
promiseMsg message
nt nodeNetwork
}
//Acceptor process detail logic.
func (a *acceptor) run() {
for {
// log.Println("acceptor:", a.id, " wait to recev msg")
m := a.nt.recev()
if m == nil {
continue
}
// log.Println("acceptor:", a.id, " recev message ", *m)
switch m.typ {
case Prepare:
promiseMsg := a.recevPrepare(*m)
a.nt.send(*promiseMsg)
continue
case Propose:
accepted := a.recevPropose(*m)
if accepted {
for _, lId := range a.learners {
m.from = a.id
m.to = lId
m.typ = Accept
a.nt.send(*m)
}
}
default:
log.Fatalln("Unsupport message in accpetor ID:", a.id)
}
}
log.Println("accetor :", a.id, " leave.")
}
//After acceptor receive prepare message.
//It will check prepare number and return acceptor if it is bigest one.
func (a *acceptor) recevPrepare(prepare message) *message {
if a.promiseMsg.getProposeSeq() >= prepare.getProposeSeq() {
log.Println("ID:", a.id, "Already accept bigger one")
return nil
}
log.Println("ID:", a.id, " Promise")
prepare.to = prepare.from
prepare.from = a.id
prepare.typ = Promise
a.acceptMsg = prepare
return &prepare
}
//Recev Propose only check if acceptor already accept bigger propose before.
//Otherwise, will just forward this message out and change its type to "Accept" to learning later.
func (a *acceptor) recevPropose(proposeMsg message) bool {
//Already accept message is identical with previous promise message
log.Println("accept:check propose. ", a.acceptMsg.getProposeSeq(), proposeMsg.getProposeSeq())
if a.acceptMsg.getProposeSeq() > proposeMsg.getProposeSeq() || a.acceptMsg.getProposeSeq() < proposeMsg.getProposeSeq() {
log.Println("ID:", a.id, " acceptor not take propose:", proposeMsg.val)
return false
}
log.Println("ID:", a.id, " Accept")
return true
}