Skip to content

Commit 4274764

Browse files
committed
sbft: consolidate replica state
Instead of maintaining the state of a remote replica spread out over several maps, instead maintain the state in a single structure. Change-Id: Idbc9915e5e824116675ad485a297caa10b7a7518 Signed-off-by: Simon Schubert <[email protected]>
1 parent 3b52a9f commit 4274764

File tree

6 files changed

+44
-35
lines changed

6 files changed

+44
-35
lines changed

consensus/simplebft/backlog.go

+9-6
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ limitations under the License.
1717
package simplebft
1818

1919
func (s *SBFT) testBacklog(m *Msg, src uint64) bool {
20-
if len(s.backLog[src]) > 0 {
20+
if len(s.replicaState[src].backLog) > 0 {
2121
return true
2222
}
2323

@@ -66,7 +66,7 @@ func (s *SBFT) recordBacklogMsg(m *Msg, src uint64) {
6666
// to make progress, the backlog processing algorithm as lined
6767
// out below will take care of starting a state transfer,
6868
// using the hello message we received on reconnect.
69-
s.backLog[src] = append(s.backLog[src], m)
69+
s.replicaState[src].backLog = append(s.replicaState[src].backLog, m)
7070
}
7171

7272
func (s *SBFT) processBacklog() {
@@ -75,14 +75,17 @@ func (s *SBFT) processBacklog() {
7575

7676
for processed {
7777
processed = false
78-
for src := range s.backLog {
79-
for len(s.backLog[src]) > 0 {
80-
m, rest := s.backLog[src][0], s.backLog[src][1:]
78+
for src := range s.replicaState {
79+
state := &s.replicaState[src]
80+
src := uint64(src)
81+
82+
for len(state.backLog) > 0 {
83+
m, rest := state.backLog[0], state.backLog[1:]
8184
if s.testBacklog2(m, src) {
8285
notReady++
8386
break
8487
}
85-
s.backLog[src] = rest
88+
state.backLog = rest
8689

8790
log.Debugf("processing stored message from %d: %s", src, m)
8891

consensus/simplebft/connection.go

+1
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,5 @@ func (s *SBFT) Connection(replica uint64) {
3939
}
4040

4141
func (s *SBFT) handleHello(h *Batch, src uint64) {
42+
s.replicaState[src].hello = h
4243
}

consensus/simplebft/newview.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ func (s *SBFT) maybeSendNewView() {
2929
vset := make(map[uint64]*Signed)
3030
var vcs []*ViewChange
3131

32-
for src, vc := range s.viewchange {
33-
if vc.vc.View == s.seq.View {
34-
vset[src] = vc.svc
35-
vcs = append(vcs, vc.vc)
32+
for src, state := range s.replicaState {
33+
if state.viewchange != nil && state.viewchange.View == s.seq.View {
34+
vset[uint64(src)] = state.signedViewchange
35+
vcs = append(vcs, state.viewchange)
3636
}
3737
}
3838

@@ -73,7 +73,7 @@ func (s *SBFT) handleNewView(nv *NewView, src uint64) {
7373
return
7474
}
7575

76-
if onv, ok := s.newview[s.primaryIDView(nv.View)]; ok && onv.View >= nv.View {
76+
if onv := s.replicaState[s.primaryIDView(nv.View)].newview; onv != nil && onv.View >= nv.View {
7777
log.Debugf("discarding duplicate new view for %d", nv.View)
7878
return
7979
}
@@ -128,7 +128,7 @@ func (s *SBFT) handleNewView(nv *NewView, src uint64) {
128128
return
129129
}
130130

131-
s.newview[s.primaryIDView(nv.View)] = nv
131+
s.replicaState[s.primaryIDView(nv.View)].newview = nv
132132

133133
s.processNewView()
134134
}
@@ -138,8 +138,8 @@ func (s *SBFT) processNewView() {
138138
return
139139
}
140140

141-
nv, ok := s.newview[s.primaryIDView(s.seq.View)]
142-
if !ok || nv.View != s.seq.View {
141+
nv := s.replicaState[s.primaryIDView(s.seq.View)].newview
142+
if nv == nil || nv.View != s.seq.View {
143143
return
144144
}
145145

consensus/simplebft/simplebft.go

+8-10
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,10 @@ type SBFT struct {
6161
batchTimer Canceller
6262
cur reqInfo
6363
activeView bool
64-
viewchange map[uint64]*viewChangeInfo
65-
newview map[uint64]*NewView
6664
lastNewViewSent uint64
6765
viewChangeTimeout time.Duration
6866
viewChangeTimer Canceller
69-
70-
backLog map[uint64][]*Msg
67+
replicaState []replicaInfo
7168
}
7269

7370
type reqInfo struct {
@@ -82,9 +79,12 @@ type reqInfo struct {
8279
checkpointDone bool
8380
}
8481

85-
type viewChangeInfo struct {
86-
svc *Signed
87-
vc *ViewChange
82+
type replicaInfo struct {
83+
backLog []*Msg
84+
hello *Batch
85+
signedViewchange *Signed
86+
viewchange *ViewChange
87+
newview *NewView
8888
}
8989

9090
var log = logging.MustGetLogger("sbft")
@@ -103,10 +103,8 @@ func New(id uint64, config *Config, sys System) (*SBFT, error) {
103103
config: *config,
104104
sys: sys,
105105
id: id,
106-
viewchange: make(map[uint64]*viewChangeInfo),
107-
newview: make(map[uint64]*NewView),
108106
viewChangeTimer: dummyCanceller{},
109-
backLog: make(map[uint64][]*Msg),
107+
replicaState: make([]replicaInfo, config.N),
110108
}
111109
s.sys.SetReceiver(s)
112110

consensus/simplebft/simplebft_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ var testLog = logging.MustGetLogger("test")
2929

3030
func init() {
3131
logging.SetLevel(logging.NOTICE, "")
32-
logging.SetLevel(logging.NOTICE, "test")
32+
logging.SetLevel(logging.DEBUG, "test")
3333
logging.SetLevel(logging.DEBUG, "sbft")
3434
}
3535

consensus/simplebft/viewchange.go

+17-10
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ func (s *SBFT) sendViewChange() {
2222
s.seq.View = s.nextView()
2323
s.cur.timeout.Cancel()
2424
s.activeView = false
25-
for r, vs := range s.viewchange {
26-
if vs.vc.View < s.seq.View {
27-
delete(s.viewchange, r)
25+
for src := range s.replicaState {
26+
state := &s.replicaState[src]
27+
if state.viewchange != nil && state.viewchange.View < s.seq.View {
28+
state.viewchange = nil
2829
}
2930
}
3031
log.Noticef("sending viewchange for view %d", s.seq.View)
@@ -71,21 +72,27 @@ func (s *SBFT) handleViewChange(svc *Signed, src uint64) {
7172
log.Debugf("old view change from %s for view %d, we are in view %d", src, vc.View, s.seq.View)
7273
return
7374
}
74-
if ovc, ok := s.viewchange[src]; ok && vc.View <= ovc.vc.View {
75+
if ovc := s.replicaState[src].viewchange; ovc != nil && vc.View <= ovc.View {
7576
log.Noticef("duplicate view change for %d from %d", vc.View, src)
7677
return
7778
}
7879

7980
log.Infof("viewchange from %d for view %d", src, vc.View)
80-
s.viewchange[src] = &viewChangeInfo{svc: svc, vc: vc}
81+
s.replicaState[src].viewchange = vc
82+
s.replicaState[src].signedViewchange = svc
8183

82-
if len(s.viewchange) == s.oneCorrectQuorum() {
83-
min := vc.View
84-
for _, vc := range s.viewchange {
85-
if vc.vc.View < min {
86-
min = vc.vc.View
84+
min := vc.View
85+
quorum := 0
86+
for _, state := range s.replicaState {
87+
if state.viewchange != nil {
88+
quorum++
89+
if state.viewchange.View < min {
90+
min = state.viewchange.View
8791
}
8892
}
93+
}
94+
95+
if quorum == s.oneCorrectQuorum() {
8996
// catch up to the minimum view
9097
if s.seq.View < min {
9198
log.Notice("we are behind on view change, resending for newer view")

0 commit comments

Comments
 (0)