...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package quorum
16
17 import (
18 "fmt"
19 "math"
20 "sort"
21 "strings"
22 )
23
24
25 type MajorityConfig map[uint64]struct{}
26
27 func (c MajorityConfig) String() string {
28 sl := make([]uint64, 0, len(c))
29 for id := range c {
30 sl = append(sl, id)
31 }
32 sort.Slice(sl, func(i, j int) bool { return sl[i] < sl[j] })
33 var buf strings.Builder
34 buf.WriteByte('(')
35 for i := range sl {
36 if i > 0 {
37 buf.WriteByte(' ')
38 }
39 fmt.Fprint(&buf, sl[i])
40 }
41 buf.WriteByte(')')
42 return buf.String()
43 }
44
45
46
47 func (c MajorityConfig) Describe(l AckedIndexer) string {
48 if len(c) == 0 {
49 return "<empty majority quorum>"
50 }
51 type tup struct {
52 id uint64
53 idx Index
54 ok bool
55 bar int
56 }
57
58
59
60
61
62 n := len(c)
63 info := make([]tup, 0, n)
64 for id := range c {
65 idx, ok := l.AckedIndex(id)
66 info = append(info, tup{id: id, idx: idx, ok: ok})
67 }
68
69
70 sort.Slice(info, func(i, j int) bool {
71 if info[i].idx == info[j].idx {
72 return info[i].id < info[j].id
73 }
74 return info[i].idx < info[j].idx
75 })
76
77
78 for i := range info {
79 if i > 0 && info[i-1].idx < info[i].idx {
80 info[i].bar = i
81 }
82 }
83
84
85 sort.Slice(info, func(i, j int) bool {
86 return info[i].id < info[j].id
87 })
88
89 var buf strings.Builder
90
91
92 fmt.Fprint(&buf, strings.Repeat(" ", n)+" idx\n")
93 for i := range info {
94 bar := info[i].bar
95 if !info[i].ok {
96 fmt.Fprint(&buf, "?"+strings.Repeat(" ", n))
97 } else {
98 fmt.Fprint(&buf, strings.Repeat("x", bar)+">"+strings.Repeat(" ", n-bar))
99 }
100 fmt.Fprintf(&buf, " %5d (id=%d)\n", info[i].idx, info[i].id)
101 }
102 return buf.String()
103 }
104
105
106 func (c MajorityConfig) Slice() []uint64 {
107 var sl []uint64
108 for id := range c {
109 sl = append(sl, id)
110 }
111 sort.Slice(sl, func(i, j int) bool { return sl[i] < sl[j] })
112 return sl
113 }
114
115 func insertionSort(sl []uint64) {
116 a, b := 0, len(sl)
117 for i := a + 1; i < b; i++ {
118 for j := i; j > a && sl[j] < sl[j-1]; j-- {
119 sl[j], sl[j-1] = sl[j-1], sl[j]
120 }
121 }
122 }
123
124
125
126 func (c MajorityConfig) CommittedIndex(l AckedIndexer) Index {
127 n := len(c)
128 if n == 0 {
129
130
131 return math.MaxUint64
132 }
133
134
135
136
137
138
139
140
141 var stk [7]uint64
142 var srt []uint64
143 if len(stk) >= n {
144 srt = stk[:n]
145 } else {
146 srt = make([]uint64, n)
147 }
148
149 {
150
151
152
153
154 i := n - 1
155 for id := range c {
156 if idx, ok := l.AckedIndex(id); ok {
157 srt[i] = uint64(idx)
158 i--
159 }
160 }
161 }
162
163
164
165 insertionSort(srt)
166
167
168
169
170 pos := n - (n/2 + 1)
171 return Index(srt[pos])
172 }
173
174
175
176
177
178 func (c MajorityConfig) VoteResult(votes map[uint64]bool) VoteResult {
179 if len(c) == 0 {
180
181
182
183 return VoteWon
184 }
185
186 ny := [2]int{}
187
188 var missing int
189 for id := range c {
190 v, ok := votes[id]
191 if !ok {
192 missing++
193 continue
194 }
195 if v {
196 ny[1]++
197 } else {
198 ny[0]++
199 }
200 }
201
202 q := len(c)/2 + 1
203 if ny[1] >= q {
204 return VoteWon
205 }
206 if ny[1]+missing >= q {
207 return VotePending
208 }
209 return VoteLost
210 }
211
View as plain text