forked from TrueCloudLab/frostfs-node
[#1439] object: Sort nodes by priority metrics to compute GET request
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
This commit is contained in:
parent
3cd7d23f10
commit
81f4cdbb91
10 changed files with 449 additions and 11 deletions
|
@ -3,6 +3,7 @@ package placement
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"slices"
|
||||
"sync"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network"
|
||||
|
@ -23,6 +24,11 @@ type Builder interface {
|
|||
BuildPlacement(cid.ID, *oid.ID, netmap.PlacementPolicy) ([][]netmap.NodeInfo, error)
|
||||
}
|
||||
|
||||
type NodeState interface {
|
||||
// LocalNodeInfo return current node state in FrostFS API v2 NodeInfo structure.
|
||||
LocalNodeInfo() *netmap.NodeInfo
|
||||
}
|
||||
|
||||
// Option represents placement traverser option.
|
||||
type Option func(*cfg)
|
||||
|
||||
|
@ -50,6 +56,10 @@ type cfg struct {
|
|||
policy netmap.PlacementPolicy
|
||||
|
||||
builder Builder
|
||||
|
||||
metrics []Metric
|
||||
|
||||
nodeState NodeState
|
||||
}
|
||||
|
||||
const invalidOptsMsg = "invalid traverser options"
|
||||
|
@ -99,7 +109,22 @@ func NewTraverser(opts ...Option) (*Traverser, error) {
|
|||
}
|
||||
|
||||
var rem []int
|
||||
if cfg.flatSuccess != nil {
|
||||
if len(cfg.metrics) > 0 && cfg.nodeState != nil {
|
||||
rem = defaultCopiesVector(cfg.policy)
|
||||
var unsortedVector []netmap.NodeInfo
|
||||
var regularVector []netmap.NodeInfo
|
||||
for i := range rem {
|
||||
unsortedVector = append(unsortedVector, ns[i][:rem[i]]...)
|
||||
regularVector = append(regularVector, ns[i][rem[i]:]...)
|
||||
}
|
||||
rem = []int{-1, -1}
|
||||
|
||||
sortedVector, err := sortVector(cfg, unsortedVector)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ns = [][]netmap.NodeInfo{sortedVector, regularVector}
|
||||
} else if cfg.flatSuccess != nil {
|
||||
ns = flatNodes(ns)
|
||||
rem = []int{int(*cfg.flatSuccess)}
|
||||
} else {
|
||||
|
@ -157,6 +182,35 @@ func flatNodes(ns [][]netmap.NodeInfo) [][]netmap.NodeInfo {
|
|||
return [][]netmap.NodeInfo{flat}
|
||||
}
|
||||
|
||||
type nodeMetrics struct {
|
||||
index int
|
||||
metrics []int
|
||||
}
|
||||
|
||||
func sortVector(cfg *cfg, unsortedVector []netmap.NodeInfo) ([]netmap.NodeInfo, error) {
|
||||
nm := make([]nodeMetrics, len(unsortedVector))
|
||||
node := cfg.nodeState.LocalNodeInfo()
|
||||
|
||||
for i := range unsortedVector {
|
||||
m := make([]int, len(cfg.metrics))
|
||||
for j, pm := range cfg.metrics {
|
||||
m[j] = pm.CalculateValue(node, &unsortedVector[i])
|
||||
}
|
||||
nm[i] = nodeMetrics{
|
||||
index: i,
|
||||
metrics: m,
|
||||
}
|
||||
}
|
||||
slices.SortFunc(nm, func(a, b nodeMetrics) int {
|
||||
return slices.Compare(a.metrics, b.metrics)
|
||||
})
|
||||
sortedVector := make([]netmap.NodeInfo, len(unsortedVector))
|
||||
for i := range unsortedVector {
|
||||
sortedVector[i] = unsortedVector[nm[i].index]
|
||||
}
|
||||
return sortedVector, nil
|
||||
}
|
||||
|
||||
// Node is a descriptor of storage node with information required for intra-container communication.
|
||||
type Node struct {
|
||||
addresses network.AddressGroup
|
||||
|
@ -322,3 +376,17 @@ func WithCopyNumbers(v []uint32) Option {
|
|||
c.copyNumbers = v
|
||||
}
|
||||
}
|
||||
|
||||
// WithPriorityMetrics use provided priority metrics to sort nodes.
|
||||
func WithPriorityMetrics(m []Metric) Option {
|
||||
return func(c *cfg) {
|
||||
c.metrics = m
|
||||
}
|
||||
}
|
||||
|
||||
// WithNodeState provide state of the current node.
|
||||
func WithNodeState(s NodeState) Option {
|
||||
return func(c *cfg) {
|
||||
c.nodeState = s
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue