github.com/hyperledger-labs/bdls@v2.1.1+incompatible/gossip/filter/filter.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package filter
     8  
     9  import (
    10  	"math/rand"
    11  
    12  	"github.com/hyperledger/fabric/gossip/comm"
    13  	"github.com/hyperledger/fabric/gossip/discovery"
    14  	"github.com/hyperledger/fabric/gossip/util"
    15  )
    16  
    17  func init() { // do we really need this?
    18  	rand.Seed(int64(util.RandomUInt64()))
    19  }
    20  
    21  // RoutingFilter defines a predicate on a NetworkMember
    22  // It is used to assert whether a given NetworkMember should be
    23  // selected for be given a message
    24  type RoutingFilter func(discovery.NetworkMember) bool
    25  
    26  // SelectNonePolicy selects an empty set of members
    27  var SelectNonePolicy = func(discovery.NetworkMember) bool {
    28  	return false
    29  }
    30  
    31  // SelectAllPolicy selects all members given
    32  var SelectAllPolicy = func(discovery.NetworkMember) bool {
    33  	return true
    34  }
    35  
    36  // CombineRoutingFilters returns the logical AND of given routing filters
    37  func CombineRoutingFilters(filters ...RoutingFilter) RoutingFilter {
    38  	return func(member discovery.NetworkMember) bool {
    39  		for _, filter := range filters {
    40  			if !filter(member) {
    41  				return false
    42  			}
    43  		}
    44  		return true
    45  	}
    46  }
    47  
    48  // SelectPeers returns a slice of at most k peers randomly chosen from peerPool that match routingFilter filter.
    49  func SelectPeers(k int, peerPool []discovery.NetworkMember, filter RoutingFilter) []*comm.RemotePeer {
    50  	var res []*comm.RemotePeer
    51  	// Iterate over the possible candidates in random order
    52  	for _, index := range rand.Perm(len(peerPool)) {
    53  		// If we collected K peers, we can stop the iteration.
    54  		if len(res) == k {
    55  			break
    56  		}
    57  		peer := peerPool[index]
    58  		// For each one, check if it is a worthy candidate to be selected
    59  		if filter(peer) {
    60  			p := &comm.RemotePeer{PKIID: peer.PKIid, Endpoint: peer.PreferredEndpoint()}
    61  			res = append(res, p)
    62  		}
    63  	}
    64  	return res
    65  }
    66  
    67  // First returns the first peer that matches the given filter
    68  func First(peerPool []discovery.NetworkMember, filter RoutingFilter) *comm.RemotePeer {
    69  	for _, p := range peerPool {
    70  		if filter(p) {
    71  			return &comm.RemotePeer{PKIID: p.PKIid, Endpoint: p.PreferredEndpoint()}
    72  		}
    73  	}
    74  	return nil
    75  }
    76  
    77  // AnyMatch filters out peers that don't match any of the given filters
    78  func AnyMatch(peerPool []discovery.NetworkMember, filters ...RoutingFilter) []discovery.NetworkMember {
    79  	var res []discovery.NetworkMember
    80  	for _, peer := range peerPool {
    81  		for _, matches := range filters {
    82  			if matches(peer) {
    83  				res = append(res, peer)
    84  				break
    85  			}
    86  		}
    87  	}
    88  	return res
    89  }