storj/satellite/nodeselection/selector.go
Márton Elek c202929413
satellite/nodeselection: rename (NodeFilter).MatchInclude to Match
As I learned, the `Include` supposed to communicate that some internal change also "included" to the filters during the check -> filters might be stateful.

But it's not the case any more after 552242387, where we removed the only one stateful filter.

Change-Id: I7c36ddadb2defbfa3b6b67bcc115e4427ba9e083
2023-08-31 16:17:52 +02:00

98 lines
2.2 KiB
Go

// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
package nodeselection
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 []*SelectedNode
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, nodeFilter NodeFilter) []*SelectedNode {
if n <= 0 {
return nil
}
selected := []*SelectedNode{}
for _, idx := range mathrand.Perm(len(nodes)) {
node := nodes[idx]
if !nodeFilter.Match(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 []*SelectedNode
}
// SelectBySubnetFromNodes creates SelectBySubnet selector from nodes.
func SelectBySubnetFromNodes(nodes []*SelectedNode) SelectBySubnet {
bynet := map[string][]*SelectedNode{}
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, filter NodeFilter) []*SelectedNode {
if n <= 0 {
return nil
}
selected := []*SelectedNode{}
r := NewRandomOrder(len(subnets))
for r.Next() {
subnet := subnets[r.At()]
rs := NewRandomOrder(len(subnet.Nodes))
for rs.Next() {
if filter.Match(subnet.Nodes[rs.At()]) {
selected = append(selected, subnet.Nodes[rs.At()].Clone())
break
}
}
if len(selected) >= n {
break
}
}
return selected
}