github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/orderer/sbft/simplebft/backlog.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package simplebft 18 19 import "fmt" 20 21 const maxBacklogSeq = 4 22 const msgPerSeq = 3 // (pre)prepare, commit, checkpoint 23 24 func (s *SBFT) testBacklogMessage(m *Msg, src uint64) bool { 25 test := func(seq *SeqView) bool { 26 if !s.activeView { 27 return true 28 } 29 if seq.Seq > s.cur.subject.Seq.Seq || seq.View > s.view { 30 return true 31 } 32 return false 33 } 34 35 if pp := m.GetPreprepare(); pp != nil { 36 return test(pp.Seq) && !s.cur.checkpointDone 37 } else if p := m.GetPrepare(); p != nil { 38 return test(p.Seq) 39 } else if c := m.GetCommit(); c != nil { 40 return test(c.Seq) 41 } else if chk := m.GetCheckpoint(); chk != nil { 42 return test(&SeqView{Seq: chk.Seq}) 43 } 44 return false 45 } 46 47 func (s *SBFT) recordBacklogMsg(m *Msg, src uint64) { 48 if src == s.id { 49 panic(fmt.Sprintf("should never have to backlog my own message (replica ID: %d)", src)) 50 } 51 52 s.replicaState[src].backLog = append(s.replicaState[src].backLog, m) 53 54 if len(s.replicaState[src].backLog) > maxBacklogSeq*msgPerSeq { 55 log.Debugf("replica %d: backlog for %d full, discarding and reconnecting", s.id, src) 56 s.discardBacklog(src) 57 s.sys.Reconnect(s.chainId, src) 58 } 59 } 60 61 func (s *SBFT) discardBacklog(src uint64) { 62 s.replicaState[src].backLog = nil 63 } 64 65 func (s *SBFT) processBacklog() { 66 processed := true 67 68 for processed { 69 processed = false 70 for src := range s.replicaState { 71 state := &s.replicaState[src] 72 src := uint64(src) 73 74 for len(state.backLog) > 0 { 75 m, rest := state.backLog[0], state.backLog[1:] 76 if s.testBacklogMessage(m, src) { 77 break 78 } 79 state.backLog = rest 80 81 log.Debugf("replica %d: processing stored message from %d: %s", s.id, src, m) 82 83 s.handleQueueableMessage(m, src) 84 processed = true 85 } 86 } 87 } 88 }