github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/orderer/sbft/simplebft/request.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 ( 20 "time" 21 ) 22 23 // Request proposes a new request to the BFT network. 24 func (s *SBFT) Request(req []byte) { 25 log.Debugf("replica %d: broadcasting a request", s.id) 26 s.broadcast(&Msg{&Msg_Request{&Request{req}}}) 27 } 28 29 func (s *SBFT) handleRequest(req *Request, src uint64) { 30 key := hash2str(hash(req.Payload)) 31 log.Infof("replica %d: inserting %x into pending", s.id, key) 32 s.pending[key] = req 33 if s.isPrimary() && s.activeView { 34 batches, committers, valid := s.sys.Validate(s.chainId, req) 35 if !valid { 36 // this one is problematic, lets skip it 37 delete(s.pending, key) 38 return 39 } 40 s.validated[key] = valid 41 if len(batches) == 0 { 42 s.startBatchTimer() 43 } else { 44 s.batches = append(s.batches, batches...) 45 s.primarycommitters = append(s.primarycommitters, committers...) 46 s.maybeSendNextBatch() 47 } 48 } 49 } 50 51 //////////////////////////////////////////////// 52 53 func (s *SBFT) startBatchTimer() { 54 if s.batchTimer == nil { 55 s.batchTimer = s.sys.Timer(time.Duration(s.config.BatchDurationNsec), s.cutAndMaybeSend) 56 } 57 } 58 59 func (s *SBFT) cutAndMaybeSend() { 60 batch, committers := s.sys.Cut(s.chainId) 61 s.batches = append(s.batches, batch) 62 s.primarycommitters = append(s.primarycommitters, committers) 63 s.maybeSendNextBatch() 64 } 65 66 func (s *SBFT) batchSize() uint64 { 67 size := uint64(0) 68 if len(s.batches) == 0 { 69 return size 70 } 71 for _, req := range s.batches[0] { 72 size += uint64(len(req.Payload)) 73 } 74 return size 75 } 76 77 func (s *SBFT) maybeSendNextBatch() { 78 if s.batchTimer != nil { 79 s.batchTimer.Cancel() 80 s.batchTimer = nil 81 } 82 83 if !s.isPrimary() || !s.activeView { 84 return 85 } 86 87 if !s.cur.checkpointDone { 88 return 89 } 90 91 if len(s.batches) == 0 { 92 hasPending := len(s.pending) != 0 93 for k, req := range s.pending { 94 if s.validated[k] == false { 95 batches, committers, valid := s.sys.Validate(s.chainId, req) 96 s.batches = append(s.batches, batches...) 97 s.primarycommitters = append(s.primarycommitters, committers...) 98 if !valid { 99 log.Panicf("Replica %d: one of our own pending requests is erroneous.", s.id) 100 delete(s.pending, k) 101 continue 102 } 103 s.validated[k] = true 104 } 105 } 106 if len(s.batches) == 0 { 107 // if we have no pending, every req was included in batches 108 if !hasPending { 109 return 110 } 111 // we have pending reqs that were just sent for validation or 112 // were already sent (they are in s.validated) 113 batch, committers := s.sys.Cut(s.chainId) 114 s.batches = append(s.batches, batch) 115 s.primarycommitters = append(s.primarycommitters, committers) 116 } 117 } 118 119 batch := s.batches[0] 120 s.batches = s.batches[1:] 121 committers := s.primarycommitters[0] 122 s.primarycommitters = s.primarycommitters[1:] 123 s.sendPreprepare(batch, committers) 124 }