[#248] netmap: fulfill backup factor for default attribute

Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
Evgenii Stratonikov 2021-01-28 14:52:51 +03:00 committed by Alex Vanin
parent 42657aaf11
commit 5d9ef5feec
3 changed files with 70 additions and 1 deletions

View file

@ -4,9 +4,62 @@ import (
"testing" "testing"
"github.com/nspcc-dev/neofs-api-go/v2/netmap" "github.com/nspcc-dev/neofs-api-go/v2/netmap"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func TestPlacementPolicy_CBFWithEmptySelector(t *testing.T) {
nodes := []NodeInfo{
nodeInfoFromAttributes("ID", "1", "Attr", "Same"),
nodeInfoFromAttributes("ID", "2", "Attr", "Same"),
nodeInfoFromAttributes("ID", "3", "Attr", "Same"),
nodeInfoFromAttributes("ID", "4", "Attr", "Same"),
}
p1 := newPlacementPolicy(0,
[]*Replica{newReplica(2, "")},
nil, // selectors
nil, // filters
)
p2 := newPlacementPolicy(3,
[]*Replica{newReplica(2, "")},
nil, // selectors
nil, // filters
)
p3 := newPlacementPolicy(3,
[]*Replica{newReplica(2, "X")},
[]*Selector{newSelector("X", "", ClauseDistinct, 2, "*")},
nil, // filters
)
p4 := newPlacementPolicy(3,
[]*Replica{newReplica(2, "X")},
[]*Selector{newSelector("X", "Attr", ClauseSame, 2, "*")},
nil, // filters
)
nm, err := NewNetmap(NodesFromInfo(nodes))
require.NoError(t, err)
v, err := nm.GetContainerNodes(p1, nil)
require.NoError(t, err)
assert.Len(t, v.Flatten(), 4)
v, err = nm.GetContainerNodes(p2, nil)
require.NoError(t, err)
assert.Len(t, v.Flatten(), 4)
v, err = nm.GetContainerNodes(p3, nil)
require.NoError(t, err)
assert.Len(t, v.Flatten(), 4)
v, err = nm.GetContainerNodes(p4, nil)
require.NoError(t, err)
assert.Len(t, v.Flatten(), 4)
}
func TestPlacementPolicyFromV2(t *testing.T) { func TestPlacementPolicyFromV2(t *testing.T) {
pV2 := new(netmap.PlacementPolicy) pV2 := new(netmap.PlacementPolicy)

View file

@ -48,6 +48,7 @@ func GetNodesCount(_ *PlacementPolicy, s *Selector) (int, int) {
} }
// getSelection returns nodes grouped by s.attribute. // getSelection returns nodes grouped by s.attribute.
// Last argument specifies if more buckets can be used to fullfill CBF.
func (c *Context) getSelection(p *PlacementPolicy, s *Selector) ([]Nodes, error) { func (c *Context) getSelection(p *PlacementPolicy, s *Selector) ([]Nodes, error) {
bucketCount, nodesInBucket := GetNodesCount(p, s) bucketCount, nodesInBucket := GetNodesCount(p, s)
buckets := c.getSelectionBase(s) buckets := c.getSelectionBase(s)
@ -99,6 +100,17 @@ func (c *Context) getSelection(p *PlacementPolicy, s *Selector) ([]Nodes, error)
hrw.SortSliceByWeightIndex(nodes, weights, c.pivotHash) hrw.SortSliceByWeightIndex(nodes, weights, c.pivotHash)
} }
if s.Attribute() == "" {
nodes, fallback = nodes[:bucketCount], nodes[bucketCount:]
for i := range fallback {
index := i % bucketCount
if len(nodes[index]) >= maxNodesInBucket {
break
}
nodes[index] = append(nodes[index], fallback[i]...)
}
}
return nodes[:bucketCount], nil return nodes[:bucketCount], nil
} }

View file

@ -54,7 +54,11 @@ func TestPlacementPolicy_Minimal(t *testing.T) {
} }
require.NoError(t, err) require.NoError(t, err)
require.EqualValues(t, rep, len(v.Flatten())) count := int(rep * defaultCBF)
if count > len(nm.Nodes) {
count = len(nm.Nodes)
}
require.EqualValues(t, count, len(v.Flatten()))
} }
t.Run("REP 1", func(t *testing.T) { t.Run("REP 1", func(t *testing.T) {