-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathProposer.go
121 lines (102 loc) · 2.89 KB
/
Proposer.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
118
119
120
121
package main
import (
"github.com/Workiva/go-datastructures/set"
"math/rand"
"sort"
"time"
)
func random(min, max int) int {
rand.Seed(time.Now().Unix())
return rand.Intn(max - min) + min
}
type Proposer struct {
Acceptors *set.Set
Quorum int
State int
BallotNumber Ballot
Id int
}
func NewProposer(acceptors *set.Set, id int) *Proposer {
proposer := new(Proposer)
proposer.Acceptors = acceptors
proposer.Quorum = (int(acceptors.Len()) - 1) / 2
proposer.State = 0
proposer.BallotNumber = Ballot {1, id}
proposer.Id = id
return proposer
}
func (proposer *Proposer) receive(f func(x int) int) (int, bool) {
proposer.BallotNumber = proposer.generateBallotNumber()
if proposer.sendPrepare(proposer.BallotNumber) {
return proposer.sendAccept(f, proposer.BallotNumber)
} else {
return 0, false
}
}
func (proposer *Proposer) generateBallotNumber() Ballot {
return Ballot {proposer.BallotNumber.Number + random(1, 100), proposer.BallotNumber.Id}
}
func (proposer *Proposer) sendPrepare(ballotNumber Ballot) bool{
conformations := make([]Pair, 0, 0)
// TODO: надо делать в разных поток отправку prepare и проверку
for _, acceptor := range proposer.Acceptors.Flatten() {
(Acceptor*) acceptor
conformation := acceptor.prepare(ballotNumber)
if conformation.State != -1 {
conformations = append(conformations, conformation)
}
}
for true {
if len(conformations) >= proposer.Quorum+ 1 {
break
} else if len(conformations) >= proposer.Quorum+ 1 {
return false
} else {
time.Sleep(5)
}
}
sum := 0
totalListOfConfirmationValues := make([]int, 0, 0)
for _, conformation := range conformations {
sum += conformation.State
totalListOfConfirmationValues = append(totalListOfConfirmationValues, conformation.State)
}
if sum == 0 {
proposer.State = 0
} else {
proposer.State = getHighestConfirmation(conformations).State
}
return true
}
func getHighestConfirmation(conformations []Pair) Pair {
ballots := make([]Ballot, 1, 1)
for _, conformation := range conformations {
ballots = append(ballots, conformation.BallotNumber)
}
sort.Slice(ballots, func(i, j int) bool {
return ballots[j].MoreThan(ballots[i])
})
highestBallot := ballots[len(ballots) - 1]
for _, conformation := range conformations {
if conformation.BallotNumber == highestBallot {
return conformation
}
}
return conformations[0]
}
func (proposer *Proposer) sendAccept(f func(x int) int, ballotNumber Ballot) (int, bool) {
proposer.State = f(proposer.State)
acceptations := make([]Pair, 0, 0)
for id, acceptor := range proposer.Acceptors {
acceptation := acceptor.accept(ballotNumber, proposer.State)
proposer.Acceptors[id] = acceptor
if acceptation.State != -1 {
acceptations = append(acceptations, acceptation)
}
}
if len(acceptations) >= proposer.Quorum+ 1 {
return proposer.State, true
}
time.Sleep(5)
return proposer.State, false
}