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  }