/
filter.go
91 lines (78 loc) · 2.39 KB
/
filter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package filter
import (
"github.com/hyperledger/fabric/gossip/comm"
"github.com/hyperledger/fabric/gossip/discovery"
"github.com/hyperledger/fabric/gossip/util"
)
// RoutingFilter defines a predicate on a NetworkMember
// It is used to assert whether a given NetworkMember should be
// selected for be given a message
type RoutingFilter func(discovery.NetworkMember) bool
// SelectNonePolicy selects an empty set of members
var SelectNonePolicy = func(discovery.NetworkMember) bool {
return false
}
// SelectAllPolicy selects all members given
var SelectAllPolicy = func(discovery.NetworkMember) bool {
return true
}
// CombineRoutingFilters returns the logical AND of given routing filters
func CombineRoutingFilters(filters ...RoutingFilter) RoutingFilter {
return func(member discovery.NetworkMember) bool {
for _, filter := range filters {
if !filter(member) {
return false
}
}
return true
}
}
// SelectPeers returns a slice of peers that match the routing filter
func SelectPeers(k int, peerPool []discovery.NetworkMember, filter RoutingFilter) []*comm.RemotePeer {
var filteredPeers []*comm.RemotePeer
for _, peer := range peerPool {
if filter(peer) {
filteredPeers = append(filteredPeers, &comm.RemotePeer{PKIID: peer.PKIid, Endpoint: peer.PreferredEndpoint()})
}
}
var indices []int
if len(filteredPeers) <= k {
indices = make([]int, len(filteredPeers))
for i := 0; i < len(filteredPeers); i++ {
indices[i] = i
}
} else {
indices = util.GetRandomIndices(k, len(filteredPeers)-1)
}
var remotePeers []*comm.RemotePeer
for _, index := range indices {
remotePeers = append(remotePeers, filteredPeers[index])
}
return remotePeers
}
// First returns the first peer that matches the given filter
func First(peerPool []discovery.NetworkMember, filter RoutingFilter) *comm.RemotePeer {
for _, p := range peerPool {
if filter(p) {
return &comm.RemotePeer{PKIID: p.PKIid, Endpoint: p.PreferredEndpoint()}
}
}
return nil
}
// AnyMatch filters out peers that don't match any of the given filters
func AnyMatch(peerPool []discovery.NetworkMember, filters ...RoutingFilter) []discovery.NetworkMember {
var res []discovery.NetworkMember
for _, peer := range peerPool {
for _, matches := range filters {
if matches(peer) {
res = append(res, peer)
break
}
}
}
return res
}