-
Notifications
You must be signed in to change notification settings - Fork 402
/
selector.go
95 lines (73 loc) · 2.12 KB
/
selector.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
92
93
94
95
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
package uploadselection
import (
mathrand "math/rand" // Using mathrand here because crypto-graphic randomness is not required and simplifies code.
)
// SelectByID implements selection from nodes with every node having equal probability.
type SelectByID []*Node
var _ Selector = (SelectByID)(nil)
// Count returns the number of maximum number of nodes that it can return.
func (nodes SelectByID) Count() int { return len(nodes) }
// Select selects upto n nodes.
func (nodes SelectByID) Select(n int, criteria Criteria) []*Node {
if n <= 0 {
return nil
}
selected := []*Node{}
for _, idx := range mathrand.Perm(len(nodes)) {
node := nodes[idx]
if !criteria.MatchInclude(node) {
continue
}
selected = append(selected, node.Clone())
if len(selected) >= n {
break
}
}
return selected
}
// SelectBySubnet implements selection from nodes with every subnet having equal probability.
type SelectBySubnet []Subnet
var _ Selector = (SelectBySubnet)(nil)
// Subnet groups together nodes with the same subnet.
type Subnet struct {
Net string
Nodes []*Node
}
// SelectBySubnetFromNodes creates SelectBySubnet selector from nodes.
func SelectBySubnetFromNodes(nodes []*Node) SelectBySubnet {
bynet := map[string][]*Node{}
for _, node := range nodes {
bynet[node.LastNet] = append(bynet[node.LastNet], node)
}
var subnets SelectBySubnet
for net, nodes := range bynet {
subnets = append(subnets, Subnet{
Net: net,
Nodes: nodes,
})
}
return subnets
}
// Count returns the number of maximum number of nodes that it can return.
func (subnets SelectBySubnet) Count() int { return len(subnets) }
// Select selects upto n nodes.
func (subnets SelectBySubnet) Select(n int, criteria Criteria) []*Node {
if n <= 0 {
return nil
}
selected := []*Node{}
for _, idx := range mathrand.Perm(len(subnets)) {
subnet := subnets[idx]
node := subnet.Nodes[mathrand.Intn(len(subnet.Nodes))]
if !criteria.MatchInclude(node) {
continue
}
selected = append(selected, node.Clone())
if len(selected) >= n {
break
}
}
return selected
}