github.com/lzy4123/fabric@v2.1.1+incompatible/gossip/comm/ack.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package comm
     8  
     9  import (
    10  	"github.com/hyperledger/fabric/gossip/common"
    11  	"github.com/hyperledger/fabric/gossip/protoext"
    12  	"github.com/hyperledger/fabric/gossip/util"
    13  )
    14  
    15  type sendFunc func(peer *RemotePeer, msg *protoext.SignedGossipMessage)
    16  type waitFunc func(*RemotePeer) error
    17  
    18  type ackSendOperation struct {
    19  	snd        sendFunc
    20  	waitForAck waitFunc
    21  }
    22  
    23  func newAckSendOperation(snd sendFunc, waitForAck waitFunc) *ackSendOperation {
    24  	return &ackSendOperation{
    25  		snd:        snd,
    26  		waitForAck: waitForAck,
    27  	}
    28  }
    29  
    30  func (aso *ackSendOperation) send(msg *protoext.SignedGossipMessage, minAckNum int, peers ...*RemotePeer) []SendResult {
    31  	successAcks := 0
    32  	results := []SendResult{}
    33  
    34  	acks := make(chan SendResult, len(peers))
    35  	// Send to all peers the message
    36  	for _, p := range peers {
    37  		go func(p *RemotePeer) {
    38  			// Send the message to 'p'
    39  			aso.snd(p, msg)
    40  			// Wait for an ack from 'p', or get an error if timed out
    41  			err := aso.waitForAck(p)
    42  			acks <- SendResult{
    43  				RemotePeer: *p,
    44  				error:      err,
    45  			}
    46  		}(p)
    47  	}
    48  	for {
    49  		ack := <-acks
    50  		results = append(results, SendResult{
    51  			error:      ack.error,
    52  			RemotePeer: ack.RemotePeer,
    53  		})
    54  		if ack.error == nil {
    55  			successAcks++
    56  		}
    57  		if successAcks == minAckNum || len(results) == len(peers) {
    58  			break
    59  		}
    60  	}
    61  	return results
    62  }
    63  
    64  func interceptAcks(nextHandler handler, remotePeerID common.PKIidType, pubSub *util.PubSub) func(*protoext.SignedGossipMessage) {
    65  	return func(m *protoext.SignedGossipMessage) {
    66  		if protoext.IsAck(m.GossipMessage) {
    67  			topic := topicForAck(m.Nonce, remotePeerID)
    68  			pubSub.Publish(topic, m.GetAck())
    69  			return
    70  		}
    71  		nextHandler(m)
    72  	}
    73  }