[#168] netmap: Replace pointer slices with non-pointer slices

- []*Replica => []Replica
 - []*Selector => []Selector
 - []*Filter => []Filter
 - []*NetworkParameter => []NetworkParameter
 - []*Node => []Node

Also introduces `filter.id()`` function to store filters
in numCache map.

Signed-off-by: Alex Vanin <alexey@nspcc.ru>
This commit is contained in:
Alex Vanin 2022-03-11 12:13:08 +03:00 committed by Alex Vanin
parent e70bf05fb9
commit cdcbaa1677
15 changed files with 114 additions and 127 deletions

View file

@ -18,7 +18,7 @@ type Context struct {
Selections map[string][]Nodes Selections map[string][]Nodes
// numCache stores parsed numeric values. // numCache stores parsed numeric values.
numCache map[*Filter]uint64 numCache map[string]uint64
// pivot is a seed for HRW. // pivot is a seed for HRW.
pivot []byte pivot []byte
// pivotHash is a saved HRW hash of pivot // pivotHash is a saved HRW hash of pivot
@ -56,7 +56,7 @@ func NewContext(nm *Netmap) *Context {
Selectors: make(map[string]*Selector), Selectors: make(map[string]*Selector),
Selections: make(map[string][]Nodes), Selections: make(map[string][]Nodes),
numCache: make(map[*Filter]uint64), numCache: make(map[string]uint64),
aggregator: newMeanIQRAgg, aggregator: newMeanIQRAgg,
weightFunc: GetDefaultWeightFunc(nm.Nodes), weightFunc: GetDefaultWeightFunc(nm.Nodes),
cbf: defaultCBF, cbf: defaultCBF,

View file

@ -21,8 +21,9 @@ func (c *Context) applyFilter(name string, b *Node) bool {
// processFilters processes filters and returns error is any of them is invalid. // processFilters processes filters and returns error is any of them is invalid.
func (c *Context) processFilters(p *PlacementPolicy) error { func (c *Context) processFilters(p *PlacementPolicy) error {
for _, f := range p.Filters() { filters := p.Filters()
if err := c.processFilter(f, true); err != nil { for i := range filters {
if err := c.processFilter(&filters[i], true); err != nil {
return err return err
} }
} }
@ -50,7 +51,7 @@ func (c *Context) processFilter(f *Filter, top bool) error {
switch f.Operation() { switch f.Operation() {
case OpAND, OpOR: case OpAND, OpOR:
for _, flt := range f.InnerFilters() { for _, flt := range f.InnerFilters() {
if err := c.processFilter(flt, false); err != nil { if err := c.processFilter(&flt, false); err != nil {
return err return err
} }
} }
@ -69,7 +70,7 @@ func (c *Context) processFilter(f *Filter, top bool) error {
return fmt.Errorf("%w: '%s'", ErrInvalidNumber, f.Value()) return fmt.Errorf("%w: '%s'", ErrInvalidNumber, f.Value())
} }
c.numCache[f] = n c.numCache[f.Value()] = n
default: default:
return fmt.Errorf("%w: %s", ErrInvalidFilterOp, f.Operation()) return fmt.Errorf("%w: %s", ErrInvalidFilterOp, f.Operation())
} }
@ -90,10 +91,10 @@ func (c *Context) match(f *Filter, b *Node) bool {
case OpAND, OpOR: case OpAND, OpOR:
for _, lf := range f.InnerFilters() { for _, lf := range f.InnerFilters() {
if lf.Name() != "" { if lf.Name() != "" {
lf = c.Filters[lf.Name()] lf = *c.Filters[lf.Name()]
} }
ok := c.match(lf, b) ok := c.match(&lf, b)
if ok == (f.Operation() == OpOR) { if ok == (f.Operation() == OpOR) {
return ok return ok
} }
@ -132,13 +133,13 @@ func (c *Context) matchKeyValue(f *Filter, b *Node) bool {
switch f.Operation() { switch f.Operation() {
case OpGT: case OpGT:
return attr > c.numCache[f] return attr > c.numCache[f.Value()]
case OpGE: case OpGE:
return attr >= c.numCache[f] return attr >= c.numCache[f.Value()]
case OpLT: case OpLT:
return attr < c.numCache[f] return attr < c.numCache[f.Value()]
case OpLE: case OpLE:
return attr <= c.numCache[f] return attr <= c.numCache[f.Value()]
default: default:
// do nothing and return false // do nothing and return false
} }
@ -214,31 +215,31 @@ func (f *Filter) SetOperation(op Operation) {
(*netmap.Filter)(f).SetOp(op.ToV2()) (*netmap.Filter)(f).SetOp(op.ToV2())
} }
func filtersFromV2(fs []*netmap.Filter) []*Filter { func filtersFromV2(fs []netmap.Filter) []Filter {
if fs == nil { if fs == nil {
return nil return nil
} }
res := make([]*Filter, 0, len(fs)) res := make([]Filter, len(fs))
for i := range fs { for i := range fs {
res = append(res, NewFilterFromV2(fs[i])) res[i] = *NewFilterFromV2(&fs[i])
} }
return res return res
} }
// InnerFilters returns list of inner filters. // InnerFilters returns list of inner filters.
func (f *Filter) InnerFilters() []*Filter { func (f *Filter) InnerFilters() []Filter {
return filtersFromV2((*netmap.Filter)(f).GetFilters()) return filtersFromV2((*netmap.Filter)(f).GetFilters())
} }
func filtersToV2(fs []*Filter) (fsV2 []*netmap.Filter) { func filtersToV2(fs []Filter) (fsV2 []netmap.Filter) {
if fs != nil { if fs != nil {
fsV2 = make([]*netmap.Filter, 0, len(fs)) fsV2 = make([]netmap.Filter, len(fs))
for i := range fs { for i := range fs {
fsV2 = append(fsV2, fs[i].ToV2()) fsV2[i] = *fs[i].ToV2()
} }
} }
@ -246,7 +247,7 @@ func filtersToV2(fs []*Filter) (fsV2 []*netmap.Filter) {
} }
// SetInnerFilters sets list of inner filters. // SetInnerFilters sets list of inner filters.
func (f *Filter) SetInnerFilters(fs ...*Filter) { func (f *Filter) SetInnerFilters(fs ...Filter) {
(*netmap.Filter)(f). (*netmap.Filter)(f).
SetFilters(filtersToV2(fs)) SetFilters(filtersToV2(fs))
} }

View file

@ -9,7 +9,7 @@ import (
) )
func TestContext_ProcessFilters(t *testing.T) { func TestContext_ProcessFilters(t *testing.T) {
fs := []*Filter{ fs := []Filter{
newFilter("StorageSSD", "Storage", "SSD", OpEQ), newFilter("StorageSSD", "Storage", "SSD", OpEQ),
newFilter("GoodRating", "Rating", "4", OpGE), newFilter("GoodRating", "Rating", "4", OpGE),
newFilter("Main", "", "", OpAND, newFilter("Main", "", "", OpAND,
@ -24,17 +24,17 @@ func TestContext_ProcessFilters(t *testing.T) {
require.NoError(t, c.processFilters(p)) require.NoError(t, c.processFilters(p))
require.Equal(t, 3, len(c.Filters)) require.Equal(t, 3, len(c.Filters))
for _, f := range fs { for _, f := range fs {
require.Equal(t, f, c.Filters[f.Name()]) require.Equal(t, f, *c.Filters[f.Name()])
} }
require.Equal(t, uint64(4), c.numCache[fs[1]]) require.Equal(t, uint64(4), c.numCache[fs[1].Value()])
require.Equal(t, uint64(123), c.numCache[fs[2].InnerFilters()[1]]) require.Equal(t, uint64(123), c.numCache[fs[2].InnerFilters()[1].Value()])
} }
func TestContext_ProcessFiltersInvalid(t *testing.T) { func TestContext_ProcessFiltersInvalid(t *testing.T) {
errTestCases := []struct { errTestCases := []struct {
name string name string
filter *Filter filter Filter
err error err error
}{ }{
{ {
@ -69,16 +69,11 @@ func TestContext_ProcessFiltersInvalid(t *testing.T) {
newFilter("*", "Rating", "3", OpGE), newFilter("*", "Rating", "3", OpGE),
ErrInvalidFilterName, ErrInvalidFilterName,
}, },
{
"MissingFilter",
nil,
ErrMissingField,
},
} }
for _, tc := range errTestCases { for _, tc := range errTestCases {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
c := NewContext(new(Netmap)) c := NewContext(new(Netmap))
p := newPlacementPolicy(1, nil, nil, []*Filter{tc.filter}) p := newPlacementPolicy(1, nil, nil, []Filter{tc.filter})
err := c.processFilters(p) err := c.processFilters(p)
require.True(t, errors.Is(err, tc.err), "got: %v", err) require.True(t, errors.Is(err, tc.err), "got: %v", err)
}) })
@ -93,12 +88,12 @@ func TestFilter_MatchSimple_InvalidOp(t *testing.T) {
f := newFilter("Main", "Rating", "5", OpEQ) f := newFilter("Main", "Rating", "5", OpEQ)
c := NewContext(new(Netmap)) c := NewContext(new(Netmap))
p := newPlacementPolicy(1, nil, nil, []*Filter{f}) p := newPlacementPolicy(1, nil, nil, []Filter{f})
require.NoError(t, c.processFilters(p)) require.NoError(t, c.processFilters(p))
// just for the coverage // just for the coverage
f.SetOperation(0) f.SetOperation(0)
require.False(t, c.match(f, b)) require.False(t, c.match(&f, b))
} }
func testFilter() *Filter { func testFilter() *Filter {
@ -174,11 +169,11 @@ func TestFilter_Operation(t *testing.T) {
func TestFilter_InnerFilters(t *testing.T) { func TestFilter_InnerFilters(t *testing.T) {
f := NewFilter() f := NewFilter()
f1, f2 := testFilter(), testFilter() f1, f2 := *testFilter(), *testFilter()
f.SetInnerFilters(f1, f2) f.SetInnerFilters(f1, f2)
require.Equal(t, []*Filter{f1, f2}, f.InnerFilters()) require.Equal(t, []Filter{f1, f2}, f.InnerFilters())
} }
func TestFilterEncoding(t *testing.T) { func TestFilterEncoding(t *testing.T) {
@ -190,7 +185,7 @@ func TestFilterEncoding(t *testing.T) {
data, err := f.Marshal() data, err := f.Marshal()
require.NoError(t, err) require.NoError(t, err)
f2 := NewFilter() f2 := *NewFilter()
require.NoError(t, f2.Unmarshal(data)) require.NoError(t, f2.Unmarshal(data))
require.Equal(t, f, f2) require.Equal(t, f, f2)
@ -200,7 +195,7 @@ func TestFilterEncoding(t *testing.T) {
data, err := f.MarshalJSON() data, err := f.MarshalJSON()
require.NoError(t, err) require.NoError(t, err)
f2 := NewFilter() f2 := *NewFilter()
require.NoError(t, f2.UnmarshalJSON(data)) require.NoError(t, f2.UnmarshalJSON(data))
require.Equal(t, f, f2) require.Equal(t, f, f2)

View file

@ -6,8 +6,7 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func newFilter(name string, k, v string, op Operation, fs ...*Filter) *Filter { func newFilter(name string, k, v string, op Operation, fs ...Filter) (f Filter) {
f := NewFilter()
f.SetName(name) f.SetName(name)
f.SetKey(k) f.SetKey(k)
f.SetOperation(op) f.SetOperation(op)
@ -16,8 +15,7 @@ func newFilter(name string, k, v string, op Operation, fs ...*Filter) *Filter {
return f return f
} }
func newSelector(name string, attr string, c Clause, count uint32, filter string) *Selector { func newSelector(name string, attr string, c Clause, count uint32, filter string) (s Selector) {
s := NewSelector()
s.SetName(name) s.SetName(name)
s.SetAttribute(attr) s.SetAttribute(attr)
s.SetCount(count) s.SetCount(count)
@ -26,7 +24,7 @@ func newSelector(name string, attr string, c Clause, count uint32, filter string
return s return s
} }
func newPlacementPolicy(bf uint32, rs []*Replica, ss []*Selector, fs []*Filter) *PlacementPolicy { func newPlacementPolicy(bf uint32, rs []Replica, ss []Selector, fs []Filter) *PlacementPolicy {
p := NewPlacementPolicy() p := NewPlacementPolicy()
p.SetContainerBackupFactor(bf) p.SetContainerBackupFactor(bf)
p.SetReplicas(rs...) p.SetReplicas(rs...)
@ -35,17 +33,15 @@ func newPlacementPolicy(bf uint32, rs []*Replica, ss []*Selector, fs []*Filter)
return p return p
} }
func newReplica(c uint32, s string) *Replica { func newReplica(c uint32, s string) (r Replica) {
r := NewReplica()
r.SetCount(c) r.SetCount(c)
r.SetSelector(s) r.SetSelector(s)
return r return r
} }
func nodeInfoFromAttributes(props ...string) NodeInfo { func nodeInfoFromAttributes(props ...string) NodeInfo {
attrs := make([]*NodeAttribute, len(props)/2) attrs := make([]NodeAttribute, len(props)/2)
for i := range attrs { for i := range attrs {
attrs[i] = NewNodeAttribute()
attrs[i].SetKey(props[i*2]) attrs[i].SetKey(props[i*2])
attrs[i].SetValue(props[i*2+1]) attrs[i].SetValue(props[i*2+1])
} }

View file

@ -63,10 +63,6 @@ func (m *Netmap) GetContainerNodes(p *PlacementPolicy, pivot []byte) (ContainerN
result := make([]Nodes, len(p.Replicas())) result := make([]Nodes, len(p.Replicas()))
for i, r := range p.Replicas() { for i, r := range p.Replicas() {
if r == nil {
return nil, fmt.Errorf("%w: REPLICA", ErrMissingField)
}
if r.Selector() == "" { if r.Selector() == "" {
if len(p.Selectors()) == 0 { if len(p.Selectors()) == 0 {
s := new(Selector) s := new(Selector)

View file

@ -187,16 +187,16 @@ func (x *NetworkConfig) IterateParameters(f func(*NetworkParameter) bool) {
} }
// Value returns value of the network parameter. // Value returns value of the network parameter.
func (x *NetworkConfig) SetParameters(ps ...*NetworkParameter) { func (x *NetworkConfig) SetParameters(ps ...NetworkParameter) {
var psV2 []*netmap.NetworkParameter var psV2 []netmap.NetworkParameter
if ps != nil { if ps != nil {
ln := len(ps) ln := len(ps)
psV2 = make([]*netmap.NetworkParameter, 0, ln) psV2 = make([]netmap.NetworkParameter, ln)
for i := 0; i < ln; i++ { for i := 0; i < ln; i++ {
psV2 = append(psV2, ps[i].ToV2()) psV2[i] = *ps[i].ToV2()
} }
} }

View file

@ -72,19 +72,19 @@ func TestNetworkConfig_SetParameters(t *testing.T) {
require.Zero(t, called) require.Zero(t, called)
pps := []*NetworkParameter{ pps := []NetworkParameter{
netmaptest.NetworkParameter(), *netmaptest.NetworkParameter(),
netmaptest.NetworkParameter(), *netmaptest.NetworkParameter(),
} }
x.SetParameters(pps...) x.SetParameters(pps...)
require.EqualValues(t, len(pps), x.NumberOfParameters()) require.EqualValues(t, len(pps), x.NumberOfParameters())
var dst []*NetworkParameter var dst []NetworkParameter
x.IterateParameters(func(p *NetworkParameter) bool { x.IterateParameters(func(p *NetworkParameter) bool {
dst = append(dst, p) dst = append(dst, *p)
called++ called++
return false return false
}) })

View file

@ -20,7 +20,7 @@ type (
} }
// Nodes represents slice of graph leafs. // Nodes represents slice of graph leafs.
Nodes []*Node Nodes []Node
) )
// NodeState is an enumeration of various states of the NeoFS node. // NodeState is an enumeration of various states of the NeoFS node.
@ -110,7 +110,7 @@ func (n Nodes) Hash() uint64 {
func NodesFromInfo(infos []NodeInfo) Nodes { func NodesFromInfo(infos []NodeInfo) Nodes {
nodes := make(Nodes, len(infos)) nodes := make(Nodes, len(infos))
for i := range infos { for i := range infos {
nodes[i] = newNodeV2(i, &infos[i]) nodes[i] = *newNodeV2(i, &infos[i])
} }
return nodes return nodes
@ -142,7 +142,7 @@ func newNodeV2(index int, ni *NodeInfo) *Node {
func (n Nodes) Weights(wf weightFunc) []float64 { func (n Nodes) Weights(wf weightFunc) []float64 {
w := make([]float64, 0, len(n)) w := make([]float64, 0, len(n))
for i := range n { for i := range n {
w = append(w, wf(n[i])) w = append(w, wf(&n[i]))
} }
return w return w
@ -156,7 +156,7 @@ func (n *Node) Attribute(k string) string {
// GetBucketWeight computes weight for a Bucket. // GetBucketWeight computes weight for a Bucket.
func GetBucketWeight(ns Nodes, a aggregator, wf weightFunc) float64 { func GetBucketWeight(ns Nodes, a aggregator, wf weightFunc) float64 {
for i := range ns { for i := range ns {
a.Add(wf(ns[i])) a.Add(wf(&ns[i]))
} }
return a.Compute() return a.Compute()
@ -355,7 +355,7 @@ func (i *NodeInfo) SetAddresses(v ...string) {
} }
// Attributes returns list of the node attributes. // Attributes returns list of the node attributes.
func (i *NodeInfo) Attributes() []*NodeAttribute { func (i *NodeInfo) Attributes() []NodeAttribute {
if i == nil { if i == nil {
return nil return nil
} }
@ -366,21 +366,21 @@ func (i *NodeInfo) Attributes() []*NodeAttribute {
return nil return nil
} }
res := make([]*NodeAttribute, 0, len(as)) res := make([]NodeAttribute, len(as))
for i := range as { for ind := range as {
res = append(res, NewNodeAttributeFromV2(as[i])) res[ind] = *NewNodeAttributeFromV2(&as[ind])
} }
return res return res
} }
// SetAttributes sets list of the node attributes. // SetAttributes sets list of the node attributes.
func (i *NodeInfo) SetAttributes(as ...*NodeAttribute) { func (i *NodeInfo) SetAttributes(as ...NodeAttribute) {
asV2 := make([]*netmap.Attribute, 0, len(as)) asV2 := make([]netmap.Attribute, len(as))
for i := range as { for ind := range as {
asV2 = append(asV2, as[i].ToV2()) asV2[ind] = *as[ind].ToV2()
} }
(*netmap.NodeInfo)(i). (*netmap.NodeInfo)(i).

View file

@ -152,7 +152,7 @@ func TestNodeInfo_State(t *testing.T) {
func TestNodeInfo_Attributes(t *testing.T) { func TestNodeInfo_Attributes(t *testing.T) {
i := new(NodeInfo) i := new(NodeInfo)
as := []*NodeAttribute{testNodeAttribute(), testNodeAttribute()} as := []NodeAttribute{*testNodeAttribute(), *testNodeAttribute()}
i.SetAttributes(as...) i.SetAttributes(as...)
@ -188,7 +188,7 @@ func TestNodeInfoEncoding(t *testing.T) {
i.SetPublicKey([]byte{1, 2, 3}) i.SetPublicKey([]byte{1, 2, 3})
i.SetAddresses("192.168.0.1", "192.168.0.2") i.SetAddresses("192.168.0.1", "192.168.0.2")
i.SetState(NodeStateOnline) i.SetState(NodeStateOnline)
i.SetAttributes(testNodeAttribute()) i.SetAttributes(*testNodeAttribute())
t.Run("binary", func(t *testing.T) { t.Run("binary", func(t *testing.T) {
data, err := i.Marshal() data, err := i.Marshal()

View file

@ -46,7 +46,7 @@ func (p *PlacementPolicy) SetSubnetID(subnet *subnetid.ID) {
} }
// Replicas returns list of object replica descriptors. // Replicas returns list of object replica descriptors.
func (p *PlacementPolicy) Replicas() []*Replica { func (p *PlacementPolicy) Replicas() []Replica {
rs := (*netmap.PlacementPolicy)(p). rs := (*netmap.PlacementPolicy)(p).
GetReplicas() GetReplicas()
@ -54,24 +54,24 @@ func (p *PlacementPolicy) Replicas() []*Replica {
return nil return nil
} }
res := make([]*Replica, 0, len(rs)) res := make([]Replica, len(rs))
for i := range rs { for i := range rs {
res = append(res, NewReplicaFromV2(rs[i])) res[i] = *NewReplicaFromV2(&rs[i])
} }
return res return res
} }
// SetReplicas sets list of object replica descriptors. // SetReplicas sets list of object replica descriptors.
func (p *PlacementPolicy) SetReplicas(rs ...*Replica) { func (p *PlacementPolicy) SetReplicas(rs ...Replica) {
var rsV2 []*netmap.Replica var rsV2 []netmap.Replica
if rs != nil { if rs != nil {
rsV2 = make([]*netmap.Replica, 0, len(rs)) rsV2 = make([]netmap.Replica, len(rs))
for i := range rs { for i := range rs {
rsV2 = append(rsV2, rs[i].ToV2()) rsV2[i] = *rs[i].ToV2()
} }
} }
@ -91,7 +91,7 @@ func (p *PlacementPolicy) SetContainerBackupFactor(f uint32) {
} }
// Selector returns set of selectors to form the container's nodes subset. // Selector returns set of selectors to form the container's nodes subset.
func (p *PlacementPolicy) Selectors() []*Selector { func (p *PlacementPolicy) Selectors() []Selector {
rs := (*netmap.PlacementPolicy)(p). rs := (*netmap.PlacementPolicy)(p).
GetSelectors() GetSelectors()
@ -99,24 +99,24 @@ func (p *PlacementPolicy) Selectors() []*Selector {
return nil return nil
} }
res := make([]*Selector, 0, len(rs)) res := make([]Selector, len(rs))
for i := range rs { for i := range rs {
res = append(res, NewSelectorFromV2(rs[i])) res[i] = *NewSelectorFromV2(&rs[i])
} }
return res return res
} }
// SetSelectors sets set of selectors to form the container's nodes subset. // SetSelectors sets set of selectors to form the container's nodes subset.
func (p *PlacementPolicy) SetSelectors(ss ...*Selector) { func (p *PlacementPolicy) SetSelectors(ss ...Selector) {
var ssV2 []*netmap.Selector var ssV2 []netmap.Selector
if ss != nil { if ss != nil {
ssV2 = make([]*netmap.Selector, 0, len(ss)) ssV2 = make([]netmap.Selector, len(ss))
for i := range ss { for i := range ss {
ssV2 = append(ssV2, ss[i].ToV2()) ssV2[i] = *ss[i].ToV2()
} }
} }
@ -124,7 +124,7 @@ func (p *PlacementPolicy) SetSelectors(ss ...*Selector) {
} }
// Filters returns list of named filters to reference in selectors. // Filters returns list of named filters to reference in selectors.
func (p *PlacementPolicy) Filters() []*Filter { func (p *PlacementPolicy) Filters() []Filter {
return filtersFromV2( return filtersFromV2(
(*netmap.PlacementPolicy)(p). (*netmap.PlacementPolicy)(p).
GetFilters(), GetFilters(),
@ -132,7 +132,7 @@ func (p *PlacementPolicy) Filters() []*Filter {
} }
// SetFilters sets list of named filters to reference in selectors. // SetFilters sets list of named filters to reference in selectors.
func (p *PlacementPolicy) SetFilters(fs ...*Filter) { func (p *PlacementPolicy) SetFilters(fs ...Filter) {
(*netmap.PlacementPolicy)(p). (*netmap.PlacementPolicy)(p).
SetFilters(filtersToV2(fs)) SetFilters(filtersToV2(fs))
} }

View file

@ -10,21 +10,21 @@ import (
func TestPlacementPolicyFromV2(t *testing.T) { func TestPlacementPolicyFromV2(t *testing.T) {
pV2 := new(netmap.PlacementPolicy) pV2 := new(netmap.PlacementPolicy)
pV2.SetReplicas([]*netmap.Replica{ pV2.SetReplicas([]netmap.Replica{
testReplica().ToV2(), *testReplica().ToV2(),
testReplica().ToV2(), *testReplica().ToV2(),
}) })
pV2.SetContainerBackupFactor(3) pV2.SetContainerBackupFactor(3)
pV2.SetSelectors([]*netmap.Selector{ pV2.SetSelectors([]netmap.Selector{
testSelector().ToV2(), *testSelector().ToV2(),
testSelector().ToV2(), *testSelector().ToV2(),
}) })
pV2.SetFilters([]*netmap.Filter{ pV2.SetFilters([]netmap.Filter{
testFilter().ToV2(), *testFilter().ToV2(),
testFilter().ToV2(), *testFilter().ToV2(),
}) })
p := NewPlacementPolicyFromV2(pV2) p := NewPlacementPolicyFromV2(pV2)
@ -34,7 +34,7 @@ func TestPlacementPolicyFromV2(t *testing.T) {
func TestPlacementPolicy_Replicas(t *testing.T) { func TestPlacementPolicy_Replicas(t *testing.T) {
p := NewPlacementPolicy() p := NewPlacementPolicy()
rs := []*Replica{testReplica(), testReplica()} rs := []Replica{*testReplica(), *testReplica()}
p.SetReplicas(rs...) p.SetReplicas(rs...)
@ -52,7 +52,7 @@ func TestPlacementPolicy_ContainerBackupFactor(t *testing.T) {
func TestPlacementPolicy_Selectors(t *testing.T) { func TestPlacementPolicy_Selectors(t *testing.T) {
p := NewPlacementPolicy() p := NewPlacementPolicy()
ss := []*Selector{testSelector(), testSelector()} ss := []Selector{*testSelector(), *testSelector()}
p.SetSelectors(ss...) p.SetSelectors(ss...)
@ -61,7 +61,7 @@ func TestPlacementPolicy_Selectors(t *testing.T) {
func TestPlacementPolicy_Filters(t *testing.T) { func TestPlacementPolicy_Filters(t *testing.T) {
p := NewPlacementPolicy() p := NewPlacementPolicy()
fs := []*Filter{testFilter(), testFilter()} fs := []Filter{*testFilter(), *testFilter()}
p.SetFilters(fs...) p.SetFilters(fs...)

View file

@ -57,7 +57,7 @@ func TestReplicaEncoding(t *testing.T) {
data, err := r.Marshal() data, err := r.Marshal()
require.NoError(t, err) require.NoError(t, err)
r2 := NewReplica() r2 := *NewReplica()
require.NoError(t, r2.Unmarshal(data)) require.NoError(t, r2.Unmarshal(data))
require.Equal(t, r, r2) require.Equal(t, r, r2)
@ -67,7 +67,7 @@ func TestReplicaEncoding(t *testing.T) {
data, err := r.MarshalJSON() data, err := r.MarshalJSON()
require.NoError(t, err) require.NoError(t, err)
r2 := NewReplica() r2 := *NewReplica()
require.NoError(t, r2.UnmarshalJSON(data)) require.NoError(t, r2.UnmarshalJSON(data))
require.Equal(t, r, r2) require.Equal(t, r, r2)

View file

@ -14,19 +14,18 @@ type Selector netmap.Selector
// processSelectors processes selectors and returns error is any of them is invalid. // processSelectors processes selectors and returns error is any of them is invalid.
func (c *Context) processSelectors(p *PlacementPolicy) error { func (c *Context) processSelectors(p *PlacementPolicy) error {
for _, s := range p.Selectors() { selectors := p.Selectors()
if s == nil { for i, s := range selectors {
return fmt.Errorf("%w: SELECT", ErrMissingField) if s.Filter() != MainFilterName {
} else if s.Filter() != MainFilterName {
_, ok := c.Filters[s.Filter()] _, ok := c.Filters[s.Filter()]
if !ok { if !ok {
return fmt.Errorf("%w: SELECT FROM '%s'", ErrFilterNotFound, s.Filter()) return fmt.Errorf("%w: SELECT FROM '%s'", ErrFilterNotFound, s.Filter())
} }
} }
c.Selectors[s.Name()] = s c.Selectors[s.Name()] = &selectors[i]
result, err := c.getSelection(p, s) result, err := c.getSelection(p, &s)
if err != nil { if err != nil {
return err return err
} }
@ -141,7 +140,7 @@ func (c *Context) getSelectionBase(subnetID *subnetid.ID, s *Selector) []nodeAtt
if !BelongsToSubnet(c.Netmap.Nodes[i].NodeInfo, sid) { if !BelongsToSubnet(c.Netmap.Nodes[i].NodeInfo, sid) {
continue continue
} }
if isMain || c.match(f, c.Netmap.Nodes[i]) { if isMain || c.match(f, &c.Netmap.Nodes[i]) {
if attr == "" { if attr == "" {
// Default attribute is transparent identifier which is different for every node. // Default attribute is transparent identifier which is different for every node.
result = append(result, nodeAttrPair{attr: "", nodes: Nodes{c.Netmap.Nodes[i]}}) result = append(result, nodeAttrPair{attr: "", nodes: Nodes{c.Netmap.Nodes[i]}})

View file

@ -94,13 +94,13 @@ func BenchmarkPolicyHRWType(b *testing.B) {
const netmapSize = 100 const netmapSize = 100
p := newPlacementPolicy(1, p := newPlacementPolicy(1,
[]*Replica{ []Replica{
newReplica(1, "loc1"), newReplica(1, "loc1"),
newReplica(1, "loc2")}, newReplica(1, "loc2")},
[]*Selector{ []Selector{
newSelector("loc1", "Location", ClauseSame, 1, "loc1"), newSelector("loc1", "Location", ClauseSame, 1, "loc1"),
newSelector("loc2", "Location", ClauseSame, 1, "loc2")}, newSelector("loc2", "Location", ClauseSame, 1, "loc2")},
[]*Filter{ []Filter{
newFilter("loc1", "Location", "Shanghai", OpEQ), newFilter("loc1", "Location", "Shanghai", OpEQ),
newFilter("loc2", "Location", "Shanghai", OpNE), newFilter("loc2", "Location", "Shanghai", OpNE),
}) })
@ -139,13 +139,13 @@ func TestPlacementPolicy_DeterministicOrder(t *testing.T) {
const netmapSize = 100 const netmapSize = 100
p := newPlacementPolicy(1, p := newPlacementPolicy(1,
[]*Replica{ []Replica{
newReplica(1, "loc1"), newReplica(1, "loc1"),
newReplica(1, "loc2")}, newReplica(1, "loc2")},
[]*Selector{ []Selector{
newSelector("loc1", "Location", ClauseSame, 1, "loc1"), newSelector("loc1", "Location", ClauseSame, 1, "loc1"),
newSelector("loc2", "Location", ClauseSame, 1, "loc2")}, newSelector("loc2", "Location", ClauseSame, 1, "loc2")},
[]*Filter{ []Filter{
newFilter("loc1", "Location", "Shanghai", OpEQ), newFilter("loc1", "Location", "Shanghai", OpEQ),
newFilter("loc2", "Location", "Shanghai", OpNE), newFilter("loc2", "Location", "Shanghai", OpNE),
}) })
@ -188,13 +188,13 @@ func TestPlacementPolicy_DeterministicOrder(t *testing.T) {
func TestPlacementPolicy_ProcessSelectors(t *testing.T) { func TestPlacementPolicy_ProcessSelectors(t *testing.T) {
p := newPlacementPolicy(2, nil, p := newPlacementPolicy(2, nil,
[]*Selector{ []Selector{
newSelector("SameRU", "City", ClauseSame, 2, "FromRU"), newSelector("SameRU", "City", ClauseSame, 2, "FromRU"),
newSelector("DistinctRU", "City", ClauseDistinct, 2, "FromRU"), newSelector("DistinctRU", "City", ClauseDistinct, 2, "FromRU"),
newSelector("Good", "Country", ClauseDistinct, 2, "Good"), newSelector("Good", "Country", ClauseDistinct, 2, "Good"),
newSelector("Main", "Country", ClauseDistinct, 3, "*"), newSelector("Main", "Country", ClauseDistinct, 3, "*"),
}, },
[]*Filter{ []Filter{
newFilter("FromRU", "Country", "Russia", OpEQ), newFilter("FromRU", "Country", "Russia", OpEQ),
newFilter("Good", "Rating", "4", OpGE), newFilter("Good", "Rating", "4", OpGE),
}) })
@ -229,7 +229,7 @@ func TestPlacementPolicy_ProcessSelectors(t *testing.T) {
for _, res := range sel { for _, res := range sel {
require.Equal(t, nodesInBucket, len(res), targ) require.Equal(t, nodesInBucket, len(res), targ)
for j := range res { for j := range res {
require.True(t, c.applyFilter(s.Filter(), res[j]), targ) require.True(t, c.applyFilter(s.Filter(), &res[j]), targ)
} }
} }
} }
@ -298,7 +298,7 @@ func TestSelectorEncoding(t *testing.T) {
data, err := s.Marshal() data, err := s.Marshal()
require.NoError(t, err) require.NoError(t, err)
s2 := NewSelector() s2 := *NewSelector()
require.NoError(t, s2.Unmarshal(data)) require.NoError(t, s2.Unmarshal(data))
require.Equal(t, s, s2) require.Equal(t, s, s2)
@ -308,7 +308,7 @@ func TestSelectorEncoding(t *testing.T) {
data, err := s.MarshalJSON() data, err := s.MarshalJSON()
require.NoError(t, err) require.NoError(t, err)
s2 := NewSelector() s2 := *NewSelector()
require.NoError(t, s2.UnmarshalJSON(data)) require.NoError(t, s2.UnmarshalJSON(data))
require.Equal(t, s, s2) require.Equal(t, s, s2)

View file

@ -11,7 +11,7 @@ func filter(withInner bool) *netmap.Filter {
x.SetOperation(netmap.OpAND) x.SetOperation(netmap.OpAND)
if withInner { if withInner {
x.SetInnerFilters(filter(false), filter(false)) x.SetInnerFilters(*filter(false), *filter(false))
} }
return x return x
@ -50,9 +50,9 @@ func PlacementPolicy() *netmap.PlacementPolicy {
x := netmap.NewPlacementPolicy() x := netmap.NewPlacementPolicy()
x.SetContainerBackupFactor(9) x.SetContainerBackupFactor(9)
x.SetFilters(Filter(), Filter()) x.SetFilters(*Filter(), *Filter())
x.SetReplicas(Replica(), Replica()) x.SetReplicas(*Replica(), *Replica())
x.SetSelectors(Selector(), Selector()) x.SetSelectors(*Selector(), *Selector())
return x return x
} }
@ -72,8 +72,8 @@ func NetworkConfig() *netmap.NetworkConfig {
x := netmap.NewNetworkConfig() x := netmap.NewNetworkConfig()
x.SetParameters( x.SetParameters(
NetworkParameter(), *NetworkParameter(),
NetworkParameter(), *NetworkParameter(),
) )
return x return x