package netmap import ( "errors" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap" "git.frostfs.info/TrueCloudLab/hrw" ) // context of a placement build process. type context struct { // network map to operate on netMap NetMap // cache of processed filters processedFilters map[string]*netmap.Filter // cache of processed selectors processedSelectors map[string]*netmap.Selector // stores results of selector processing selections map[string][]nodes // cache of parsed numeric values numCache map[string]uint64 hrwSeed []byte // hrw.Hash of hrwSeed hrwSeedHash uint64 // weightFunc is a weighting function for determining node priority // which combines low price and high performance weightFunc weightFunc // container backup factor cbf uint32 // nodes already used in previous selections, which is needed when the placement // policy uses the UNIQUE flag. Nodes marked as used are not used in subsequent // base selections. usedNodes map[uint64]bool // If true, returns an error when netmap does not contain enough nodes for selection. // By default best effort is taken. strict bool } // Various validation errors. var ( errInvalidFilterName = errors.New("filter name is invalid") errInvalidNumber = errors.New("invalid number") errInvalidFilterOp = errors.New("invalid filter operation") errFilterNotFound = errors.New("filter not found") errNonEmptyFilters = errors.New("simple filter contains sub-filters") errNotEnoughNodes = errors.New("not enough nodes to SELECT from") errUnnamedTopFilter = errors.New("unnamed top-level filter") ) // newContext returns initialized context. func newContext(nm NetMap) *context { return &context{ netMap: nm, processedFilters: make(map[string]*netmap.Filter), processedSelectors: make(map[string]*netmap.Selector), selections: make(map[string][]nodes), numCache: make(map[string]uint64), weightFunc: defaultWeightFunc(nm.nodes), usedNodes: make(map[uint64]bool), } } func (c *context) setPivot(pivot []byte) { if len(pivot) != 0 { c.hrwSeed = pivot c.hrwSeedHash = hrw.Hash(pivot) } } func (c *context) setCBF(cbf uint32) { if cbf == 0 { c.cbf = 3 } else { c.cbf = cbf } } func (c *context) addUsedNodes(ns ...NodeInfo) { for _, n := range ns { c.usedNodes[n.hash] = true } } func defaultWeightFunc(ns nodes) weightFunc { mean := newMeanAgg() minV := newMinAgg() for i := range ns { mean.Add(float64(ns[i].capacity())) minV.Add(float64(ns[i].Price())) } return newWeightFunc( newSigmoidNorm(mean.Compute()), newReverseMinNorm(minV.Compute())) }