github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/gossip/state/state.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 state 18 19 import ( 20 "bytes" 21 "math/rand" 22 "sync" 23 "sync/atomic" 24 "time" 25 26 pb "github.com/golang/protobuf/proto" 27 "github.com/hyperledger/fabric/core/committer" 28 "github.com/hyperledger/fabric/gossip/comm" 29 common2 "github.com/hyperledger/fabric/gossip/common" 30 "github.com/hyperledger/fabric/gossip/gossip" 31 "github.com/hyperledger/fabric/gossip/util" 32 "github.com/hyperledger/fabric/protos/common" 33 proto "github.com/hyperledger/fabric/protos/gossip" 34 "github.com/op/go-logging" 35 ) 36 37 // GossipStateProvider is the interface to acquire sequences of the ledger blocks 38 // capable to full fill missing blocks by running state replication and 39 // sending request to get missing block to other nodes 40 type GossipStateProvider interface { 41 // Retrieve block with sequence number equal to index 42 GetBlock(index uint64) *common.Block 43 44 AddPayload(payload *proto.Payload) error 45 46 // Stop terminates state transfer object 47 Stop() 48 } 49 50 var remoteStateMsgFilter = func(message interface{}) bool { 51 return message.(proto.ReceivedMessage).GetGossipMessage().IsRemoteStateMessage() 52 } 53 54 const ( 55 defPollingPeriod = 200 * time.Millisecond 56 defAntiEntropyInterval = 10 * time.Second 57 ) 58 59 // GossipStateProviderImpl the implementation of the GossipStateProvider interface 60 // the struct to handle in memory sliding window of 61 // new ledger block to be acquired by hyper ledger 62 type GossipStateProviderImpl struct { 63 // Chain id 64 chainID string 65 66 // The gossiping service 67 gossip gossip.Gossip 68 69 // Channel to read gossip messages from 70 gossipChan <-chan *proto.GossipMessage 71 72 commChan <-chan proto.ReceivedMessage 73 74 // Flag which signals for termination 75 stopFlag int32 76 77 mutex sync.RWMutex 78 79 // Queue of payloads which wasn't acquired yet 80 payloads PayloadsBuffer 81 82 committer committer.Committer 83 84 logger *logging.Logger 85 86 done sync.WaitGroup 87 } 88 89 // NewGossipStateProvider creates initialized instance of gossip state provider 90 func NewGossipStateProvider(chainID string, g gossip.Gossip, committer committer.Committer) GossipStateProvider { 91 logger := util.GetLogger(util.LoggingStateModule, "") 92 93 gossipChan, _ := g.Accept(func(message interface{}) bool { 94 // Get only data messages 95 return message.(*proto.GossipMessage).IsDataMsg() && 96 bytes.Equal(message.(*proto.GossipMessage).Channel, []byte(chainID)) 97 }, false) 98 99 // Filter message which are only relevant for state transfer 100 _, commChan := g.Accept(remoteStateMsgFilter, true) 101 102 height, err := committer.LedgerHeight() 103 104 if err != nil { 105 logger.Error("Could not read ledger info to obtain current ledger height due to: ", err) 106 // Exiting as without ledger it will be impossible 107 // to deliver new blocks 108 return nil 109 } 110 111 s := &GossipStateProviderImpl{ 112 chainID: chainID, 113 114 // Instance of the gossip 115 gossip: g, 116 117 // Channel to read new messages from 118 gossipChan: gossipChan, 119 120 // Channel to read direct messages from other peers 121 commChan: commChan, 122 123 stopFlag: 0, 124 // Create a queue for payload received 125 payloads: NewPayloadsBuffer(height), 126 127 committer: committer, 128 129 logger: logger, 130 } 131 132 state := NewNodeMetastate(height - 1) 133 134 s.logger.Infof("Updating node metadata information, current ledger sequence is at = %d, next expected block is = %d", state.LedgerHeight, s.payloads.Next()) 135 bytes, err := state.Bytes() 136 if err == nil { 137 s.logger.Debug("Updating gossip metadate state", state) 138 g.UpdateChannelMetadata(bytes, common2.ChainID(s.chainID)) 139 } else { 140 s.logger.Errorf("Unable to serialize node meta state, error = %s", err) 141 } 142 143 s.done.Add(3) 144 145 // Listen for incoming communication 146 go s.listen() 147 // Deliver in order messages into the incoming channel 148 go s.deliverPayloads() 149 // Execute anti entropy to fill missing gaps 150 go s.antiEntropy() 151 152 return s 153 } 154 155 func (s *GossipStateProviderImpl) listen() { 156 for !s.isDone() { 157 // Do not block on waiting message from channel 158 // check each 500ms whenever is done indicates to 159 // finish 160 next: 161 select { 162 case msg := <-s.gossipChan: 163 { 164 s.logger.Debug("Received new message via gossip channel") 165 go s.queueNewMessage(msg) 166 } 167 case msg := <-s.commChan: 168 { 169 s.logger.Debug("Direct message ", msg) 170 go s.directMessage(msg) 171 } 172 case <-time.After(defPollingPeriod): 173 break next 174 } 175 } 176 s.logger.Debug("Stop listening for new messages") 177 s.done.Done() 178 } 179 180 func (s *GossipStateProviderImpl) directMessage(msg proto.ReceivedMessage) { 181 s.logger.Debug("[ENTER] -> directMessage") 182 defer s.logger.Debug("[EXIT] -> directMessage") 183 184 if msg == nil { 185 s.logger.Error("Got nil message via end-to-end channel, should not happen!") 186 return 187 } 188 189 if !bytes.Equal(msg.GetGossipMessage().Channel, []byte(s.chainID)) { 190 s.logger.Warning("Received state transfer request for channel", 191 string(msg.GetGossipMessage().Channel), "while expecting channel", s.chainID, "skipping request...") 192 return 193 } 194 195 incoming := msg.GetGossipMessage() 196 197 if incoming.GetStateRequest() != nil { 198 s.handleStateRequest(msg) 199 } else if incoming.GetStateResponse() != nil { 200 s.handleStateResponse(msg) 201 } 202 } 203 204 func (s *GossipStateProviderImpl) handleStateRequest(msg proto.ReceivedMessage) { 205 request := msg.GetGossipMessage().GetStateRequest() 206 response := &proto.RemoteStateResponse{Payloads: make([]*proto.Payload, 0)} 207 for _, seqNum := range request.SeqNums { 208 s.logger.Debug("Reading block ", seqNum, " from the committer service") 209 blocks := s.committer.GetBlocks([]uint64{seqNum}) 210 211 if blocks == nil || len(blocks) < 1 { 212 s.logger.Errorf("Wasn't able to read block with sequence number %d from ledger, skipping....", seqNum) 213 continue 214 } 215 216 blockBytes, err := pb.Marshal(blocks[0]) 217 if err != nil { 218 s.logger.Errorf("Could not marshal block: %s", err) 219 } 220 221 response.Payloads = append(response.Payloads, &proto.Payload{ 222 SeqNum: seqNum, 223 Data: blockBytes, 224 Hash: string(blocks[0].Header.Hash()), 225 }) 226 } 227 // Sending back response with missing blocks 228 msg.Respond(&proto.GossipMessage{ 229 Nonce: 0, 230 Tag: proto.GossipMessage_CHAN_OR_ORG, 231 Channel: []byte(s.chainID), 232 Content: &proto.GossipMessage_StateResponse{response}, 233 }) 234 } 235 236 func (s *GossipStateProviderImpl) handleStateResponse(msg proto.ReceivedMessage) { 237 response := msg.GetGossipMessage().GetStateResponse() 238 for _, payload := range response.GetPayloads() { 239 s.logger.Debugf("Received payload with sequence number %d.", payload.SeqNum) 240 err := s.payloads.Push(payload) 241 if err != nil { 242 s.logger.Warningf("Payload with sequence number %d was received earlier", payload.SeqNum) 243 } 244 } 245 } 246 247 // Internal function to check whenever we need to finish listening 248 // for new messages to arrive 249 func (s *GossipStateProviderImpl) isDone() bool { 250 return atomic.LoadInt32(&s.stopFlag) == 1 251 } 252 253 // Stop function send halting signal to all go routines 254 func (s *GossipStateProviderImpl) Stop() { 255 atomic.StoreInt32(&s.stopFlag, 1) 256 s.done.Wait() 257 s.committer.Close() 258 } 259 260 // New message notification/handler 261 func (s *GossipStateProviderImpl) queueNewMessage(msg *proto.GossipMessage) { 262 if !bytes.Equal(msg.Channel, []byte(s.chainID)) { 263 s.logger.Warning("Received state transfer request for channel", 264 string(msg.Channel), "while expecting channel", s.chainID, "skipping request...") 265 return 266 } 267 268 dataMsg := msg.GetDataMsg() 269 if dataMsg != nil { 270 // Add new payload to ordered set 271 s.logger.Debugf("Received new payload with sequence number = [%d]", dataMsg.Payload.SeqNum) 272 s.payloads.Push(dataMsg.GetPayload()) 273 } else { 274 s.logger.Debug("Gossip message received is not of data message type, usually this should not happen.") 275 } 276 } 277 278 func (s *GossipStateProviderImpl) deliverPayloads() { 279 for !s.isDone() { 280 next: 281 select { 282 // Wait for notification that next seq has arrived 283 case <-s.payloads.Ready(): 284 { 285 s.logger.Debugf("Ready to transfer payloads to the ledger, next sequence number is = [%d]", s.payloads.Next()) 286 // Collect all subsequent payloads 287 for payload := s.payloads.Pop(); payload != nil; payload = s.payloads.Pop() { 288 rawblock := &common.Block{} 289 if err := pb.Unmarshal(payload.Data, rawblock); err != nil { 290 s.logger.Errorf("Error getting block with seqNum = %d due to (%s)...dropping block", payload.SeqNum, err) 291 continue 292 } 293 s.logger.Debug("New block with sequence number ", payload.SeqNum, " transactions num ", len(rawblock.Data.Data)) 294 s.commitBlock(rawblock, payload.SeqNum) 295 } 296 } 297 case <-time.After(defPollingPeriod): 298 { 299 break next 300 } 301 } 302 } 303 s.logger.Debug("State provider has been stoped, finishing to push new blocks.") 304 s.done.Done() 305 } 306 307 func (s *GossipStateProviderImpl) antiEntropy() { 308 checkPoint := time.Now() 309 for !s.isDone() { 310 time.Sleep(defPollingPeriod) 311 if time.Since(checkPoint).Nanoseconds() <= defAntiEntropyInterval.Nanoseconds() { 312 continue 313 } 314 checkPoint = time.Now() 315 316 current, _ := s.committer.LedgerHeight() 317 max, _ := s.committer.LedgerHeight() 318 319 for _, p := range s.gossip.PeersOfChannel(common2.ChainID(s.chainID)) { 320 if state, err := FromBytes(p.Metadata); err == nil { 321 if max < state.LedgerHeight { 322 max = state.LedgerHeight 323 } 324 } 325 } 326 327 if current == max { 328 continue 329 } 330 331 s.requestBlocksInRange(uint64(current), uint64(max)) 332 } 333 s.logger.Debug("Stateprovider stopped, stopping anti entropy procedure.") 334 s.done.Done() 335 } 336 337 // GetBlocksInRange capable to acquire blocks with sequence 338 // numbers in the range [start...end]. 339 func (s *GossipStateProviderImpl) requestBlocksInRange(start uint64, end uint64) { 340 var peers []*comm.RemotePeer 341 // Filtering peers which might have relevant blocks 342 for _, netMember := range s.gossip.PeersOfChannel(common2.ChainID(s.chainID)) { 343 nodeMetadata, err := FromBytes(netMember.Metadata) 344 if err == nil { 345 if nodeMetadata.LedgerHeight >= end { 346 peers = append(peers, &comm.RemotePeer{Endpoint: netMember.PreferredEndpoint(), PKIID: netMember.PKIid}) 347 } 348 } else { 349 s.logger.Errorf("Unable to de-serialize node meta state, error = %s", err) 350 } 351 } 352 353 n := len(peers) 354 if n == 0 { 355 s.logger.Warningf("There is not peer nodes to ask for missing blocks in range [%d, %d)", start, end) 356 return 357 } 358 // Select peers to ask for blocks 359 peer := peers[rand.Intn(n)] 360 s.logger.Infof("State transfer, with peer %s, the min available sequence number %d next block %d", peer.Endpoint, start, end) 361 362 request := &proto.RemoteStateRequest{ 363 SeqNums: make([]uint64, 0), 364 } 365 366 for i := start; i <= end; i++ { 367 request.SeqNums = append(request.SeqNums, uint64(i)) 368 } 369 370 s.logger.Debug("Sending direct request to complete missing blocks,", request, "for chain", s.chainID) 371 s.gossip.Send(&proto.GossipMessage{ 372 Nonce: 0, 373 Tag: proto.GossipMessage_CHAN_OR_ORG, 374 Channel: []byte(s.chainID), 375 Content: &proto.GossipMessage_StateRequest{request}, 376 }, peer) 377 } 378 379 // GetBlock return ledger block given its sequence number as a parameter 380 func (s *GossipStateProviderImpl) GetBlock(index uint64) *common.Block { 381 // Try to read missing block from the ledger, should return no nil with 382 // content including at least one block 383 if blocks := s.committer.GetBlocks([]uint64{index}); blocks != nil && len(blocks) > 0 { 384 return blocks[0] 385 } 386 387 return nil 388 } 389 390 // AddPayload add new payload into state 391 func (s *GossipStateProviderImpl) AddPayload(payload *proto.Payload) error { 392 s.logger.Debug("Adding new payload into the buffer, seqNum = ", payload.SeqNum) 393 return s.payloads.Push(payload) 394 } 395 396 func (s *GossipStateProviderImpl) commitBlock(block *common.Block, seqNum uint64) error { 397 if err := s.committer.Commit(block); err != nil { 398 s.logger.Errorf("Got error while committing(%s)", err) 399 return err 400 } 401 402 // Update ledger level within node metadata 403 state := NewNodeMetastate(seqNum) 404 // Decode state to byte array 405 bytes, err := state.Bytes() 406 if err == nil { 407 s.gossip.UpdateChannelMetadata(bytes, common2.ChainID(s.chainID)) 408 } else { 409 s.logger.Errorf("Unable to serialize node meta state, error = %s", err) 410 } 411 412 s.logger.Debugf("Channel [%s]: Created block [%d] with %d transaction(s)", s.chainID, block.Header.Number, len(block.Data.Data)) 413 return nil 414 }