github.com/lzy4123/fabric@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 }