[#356] netmap: Return missing subnets error from IterateSubnets
Each NeoFS storage node should be present in at least one subnet. Make `netmap.IterateSubnets` function to return an error if the node by the end of the loop does not belong to any subnet. Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
parent
348f9498bd
commit
051b103df3
2 changed files with 62 additions and 6 deletions
|
@ -113,12 +113,16 @@ func WriteSubnetInfo(node *NodeInfo, info NodeSubnetInfo) {
|
||||||
// ErrRemoveSubnet is returned when a node needs to leave the subnet.
|
// ErrRemoveSubnet is returned when a node needs to leave the subnet.
|
||||||
var ErrRemoveSubnet = errors.New("remove subnet")
|
var ErrRemoveSubnet = errors.New("remove subnet")
|
||||||
|
|
||||||
|
var errNoSubnets = errors.New("no subnets")
|
||||||
|
|
||||||
// IterateSubnets iterates over all subnets the node belongs to and passes the IDs to f.
|
// IterateSubnets iterates over all subnets the node belongs to and passes the IDs to f.
|
||||||
// Handler must not be nil.
|
// Handler must not be nil.
|
||||||
//
|
//
|
||||||
// If f returns ErrRemoveSubnet, then removes subnet entry. Breaks on any other non-nil error and returns it.
|
// If f returns ErrRemoveSubnet, then removes subnet entry. Note that this leads to an instant mutation of NodeInfo.
|
||||||
|
// Breaks on any other non-nil error and returns it.
|
||||||
//
|
//
|
||||||
// Returns an error if any subnet attribute has wrong format.
|
// Returns an error if any subnet attribute has wrong format.
|
||||||
|
// Returns an error if the node is not included in any subnet by the end of the loop.
|
||||||
func IterateSubnets(node *NodeInfo, f func(refs.SubnetID) error) error {
|
func IterateSubnets(node *NodeInfo, f func(refs.SubnetID) error) error {
|
||||||
attrs := node.GetAttributes()
|
attrs := node.GetAttributes()
|
||||||
|
|
||||||
|
@ -126,6 +130,7 @@ func IterateSubnets(node *NodeInfo, f func(refs.SubnetID) error) error {
|
||||||
err error
|
err error
|
||||||
id refs.SubnetID
|
id refs.SubnetID
|
||||||
metZero bool // if zero subnet's attribute was met in for-loop
|
metZero bool // if zero subnet's attribute was met in for-loop
|
||||||
|
entries uint
|
||||||
)
|
)
|
||||||
|
|
||||||
for i := 0; i < len(attrs); i++ { // range must not be used because of attrs mutation in body
|
for i := 0; i < len(attrs); i++ { // range must not be used because of attrs mutation in body
|
||||||
|
@ -168,6 +173,7 @@ func IterateSubnets(node *NodeInfo, f func(refs.SubnetID) error) error {
|
||||||
|
|
||||||
if !isRemoveErr {
|
if !isRemoveErr {
|
||||||
// no handler's error and non-zero subnet
|
// no handler's error and non-zero subnet
|
||||||
|
entries++
|
||||||
continue
|
continue
|
||||||
} else if metZero {
|
} else if metZero {
|
||||||
// removal error and zero subnet.
|
// removal error and zero subnet.
|
||||||
|
@ -183,7 +189,10 @@ func IterateSubnets(node *NodeInfo, f func(refs.SubnetID) error) error {
|
||||||
// we can set False or remove attribute, latter is more memory/network efficient.
|
// we can set False or remove attribute, latter is more memory/network efficient.
|
||||||
attrs = append(attrs[:i], attrs[i+1:]...)
|
attrs = append(attrs[:i], attrs[i+1:]...)
|
||||||
i--
|
i--
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entries++
|
||||||
}
|
}
|
||||||
|
|
||||||
if !metZero {
|
if !metZero {
|
||||||
|
@ -199,9 +208,15 @@ func IterateSubnets(node *NodeInfo, f func(refs.SubnetID) error) error {
|
||||||
attr.SetValue(attrSubnetValExit)
|
attr.SetValue(attrSubnetValExit)
|
||||||
|
|
||||||
attrs = append(attrs, &attr)
|
attrs = append(attrs, &attr)
|
||||||
|
} else {
|
||||||
|
entries++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if entries <= 0 {
|
||||||
|
return errNoSubnets
|
||||||
|
}
|
||||||
|
|
||||||
node.SetAttributes(attrs)
|
node.SetAttributes(attrs)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -179,6 +179,15 @@ func TestSubnets(t *testing.T) {
|
||||||
t.Run("zero", func(t *testing.T) {
|
t.Run("zero", func(t *testing.T) {
|
||||||
var node netmap.NodeInfo
|
var node netmap.NodeInfo
|
||||||
|
|
||||||
|
// enter to some non-zero subnet so that zero is not the only one
|
||||||
|
var attr netmap.Attribute
|
||||||
|
|
||||||
|
attr.SetKey(subnetAttrKey("321"))
|
||||||
|
attr.SetValue("True")
|
||||||
|
|
||||||
|
attrs := []*netmap.Attribute{&attr}
|
||||||
|
node.SetAttributes(attrs)
|
||||||
|
|
||||||
err := netmap.IterateSubnets(&node, func(id refs.SubnetID) error {
|
err := netmap.IterateSubnets(&node, func(id refs.SubnetID) error {
|
||||||
if refs.IsZeroSubnet(&id) {
|
if refs.IsZeroSubnet(&id) {
|
||||||
return netmap.ErrRemoveSubnet
|
return netmap.ErrRemoveSubnet
|
||||||
|
@ -189,12 +198,19 @@ func TestSubnets(t *testing.T) {
|
||||||
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
attrs := node.GetAttributes()
|
attrs = node.GetAttributes()
|
||||||
require.Len(t, attrs, 1)
|
require.Len(t, attrs, 2)
|
||||||
|
|
||||||
attr := attrs[0]
|
found := false
|
||||||
assertSubnetAttrKey(t, attr, 0)
|
|
||||||
require.Equal(t, "False", attr.GetValue())
|
for i := range attrs {
|
||||||
|
if attrs[i].GetKey() == subnetAttrKey("0") {
|
||||||
|
require.Equal(t, "False", attrs[i].GetValue())
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
require.True(t, found)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("non-zero", func(t *testing.T) {
|
t.Run("non-zero", func(t *testing.T) {
|
||||||
|
@ -222,5 +238,30 @@ func TestSubnets(t *testing.T) {
|
||||||
attrs = node.GetAttributes()
|
attrs = node.GetAttributes()
|
||||||
require.Empty(t, attrs)
|
require.Empty(t, attrs)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("all", func(t *testing.T) {
|
||||||
|
var (
|
||||||
|
node netmap.NodeInfo
|
||||||
|
attrs []*netmap.Attribute
|
||||||
|
)
|
||||||
|
|
||||||
|
// enter to some non-zero subnet so that zero is not the only one
|
||||||
|
for i := 1; i <= 5; i++ {
|
||||||
|
var attr netmap.Attribute
|
||||||
|
|
||||||
|
attr.SetKey(subnetAttrKey(strconv.Itoa(i)))
|
||||||
|
attr.SetValue("True")
|
||||||
|
|
||||||
|
attrs = append(attrs, &attr)
|
||||||
|
}
|
||||||
|
|
||||||
|
node.SetAttributes(attrs)
|
||||||
|
|
||||||
|
err := netmap.IterateSubnets(&node, func(id refs.SubnetID) error {
|
||||||
|
return netmap.ErrRemoveSubnet
|
||||||
|
})
|
||||||
|
|
||||||
|
require.Error(t, err)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue