git.frostfs.info/TrueCloudLab/frostfs-sdk-go@v0.0.0-20241022124111-5361f0ecebd3/netmap/context.go (about) 1 package netmap 2 3 import ( 4 "errors" 5 6 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" 7 "git.frostfs.info/TrueCloudLab/hrw" 8 ) 9 10 // context of a placement build process. 11 type context struct { 12 // network map to operate on 13 netMap NetMap 14 15 // cache of processed filters 16 processedFilters map[string]*netmap.Filter 17 18 // cache of processed selectors 19 processedSelectors map[string]*netmap.Selector 20 21 // stores results of selector processing 22 selections map[string][]nodes 23 24 // cache of parsed numeric values 25 numCache map[string]uint64 26 27 hrwSeed []byte 28 29 // hrw.Hash of hrwSeed 30 hrwSeedHash uint64 31 32 // weightFunc is a weighting function for determining node priority 33 // which combines low price and high performance 34 weightFunc weightFunc 35 36 // container backup factor 37 cbf uint32 38 39 // nodes already used in previous selections, which is needed when the placement 40 // policy uses the UNIQUE flag. Nodes marked as used are not used in subsequent 41 // base selections. 42 usedNodes map[uint64]bool 43 44 // If true, returns an error when netmap does not contain enough nodes for selection. 45 // By default best effort is taken. 46 strict bool 47 } 48 49 // Various validation errors. 50 var ( 51 errInvalidFilterName = errors.New("filter name is invalid") 52 errInvalidNumber = errors.New("invalid number") 53 errInvalidFilterOp = errors.New("invalid filter operation") 54 errFilterNotFound = errors.New("filter not found") 55 errNonEmptyFilters = errors.New("simple filter contains sub-filters") 56 errNotEnoughNodes = errors.New("not enough nodes to SELECT from") 57 errUnnamedTopFilter = errors.New("unnamed top-level filter") 58 ) 59 60 // newContext returns initialized context. 61 func newContext(nm NetMap) *context { 62 return &context{ 63 netMap: nm, 64 processedFilters: make(map[string]*netmap.Filter), 65 processedSelectors: make(map[string]*netmap.Selector), 66 selections: make(map[string][]nodes), 67 68 numCache: make(map[string]uint64), 69 weightFunc: defaultWeightFunc(nm.nodes), 70 usedNodes: make(map[uint64]bool), 71 } 72 } 73 74 func (c *context) setPivot(pivot []byte) { 75 if len(pivot) != 0 { 76 c.hrwSeed = pivot 77 c.hrwSeedHash = hrw.Hash(pivot) 78 } 79 } 80 81 func (c *context) setCBF(cbf uint32) { 82 if cbf == 0 { 83 c.cbf = 3 84 } else { 85 c.cbf = cbf 86 } 87 } 88 89 func (c *context) addUsedNodes(ns ...NodeInfo) { 90 for _, n := range ns { 91 c.usedNodes[n.hash] = true 92 } 93 } 94 95 func defaultWeightFunc(ns nodes) weightFunc { 96 mean := newMeanAgg() 97 minV := newMinAgg() 98 99 for i := range ns { 100 mean.Add(float64(ns[i].capacity())) 101 minV.Add(float64(ns[i].Price())) 102 } 103 104 return newWeightFunc( 105 newSigmoidNorm(mean.Compute()), 106 newReverseMinNorm(minV.Compute())) 107 }