forked from TrueCloudLab/frostfs-api-go
[#19] subnet: Drop related types and fields
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
This commit is contained in:
parent
bd44a3f47b
commit
ff6d8db741
23 changed files with 0 additions and 1037 deletions
|
@ -4,9 +4,6 @@ package container
|
|||
const SysAttributePrefix = "__SYSTEM__"
|
||||
|
||||
const (
|
||||
// SysAttributeSubnet is a string ID of container's storage subnet.
|
||||
SysAttributeSubnet = SysAttributePrefix + "SUBNET"
|
||||
|
||||
// SysAttributeName is a string of human-friendly container name registered as the domain in NNS contract.
|
||||
SysAttributeName = SysAttributePrefix + "NAME"
|
||||
|
||||
|
@ -22,10 +19,6 @@ const (
|
|||
const SysAttributePrefixNeoFS = "__NEOFS__"
|
||||
|
||||
const (
|
||||
// SysAttributeSubnetNeoFS is a string ID of container's storage subnet.
|
||||
// Deprecated: use SysAttributeSubnet
|
||||
SysAttributeSubnetNeoFS = SysAttributePrefixNeoFS + "SUBNET"
|
||||
|
||||
// SysAttributeNameNeoFS is a string of human-friendly container name registered as the domain in NNS contract.
|
||||
// Deprecated: use SysAttributeName
|
||||
SysAttributeNameNeoFS = SysAttributePrefixNeoFS + "NAME"
|
||||
|
|
BIN
container/grpc/types.pb.go
generated
BIN
container/grpc/types.pb.go
generated
Binary file not shown.
|
@ -1,232 +0,0 @@
|
|||
package netmap
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
)
|
||||
|
||||
// prefix of keys to subnet attributes.
|
||||
const attrSubnetPrefix = "__SYSTEM__SUBNET_"
|
||||
|
||||
// prefix of keys to subnet attributes.
|
||||
// Deprecated: use attrSubnetPrefix
|
||||
const attrSubnetPrefixNeoFS = "__NEOFS__SUBNET_"
|
||||
|
||||
const (
|
||||
// subnet attribute's value denoting subnet entry
|
||||
attrSubnetValEntry = "True"
|
||||
|
||||
// subnet attribute's value denoting subnet exit
|
||||
attrSubnetValExit = "False"
|
||||
)
|
||||
|
||||
// NodeSubnetInfo groups information about subnet which can be written to NodeInfo.
|
||||
//
|
||||
// Zero value represents entry to zero subnet.
|
||||
type NodeSubnetInfo struct {
|
||||
exit bool
|
||||
|
||||
id *refs.SubnetID
|
||||
}
|
||||
|
||||
// Enabled returns true iff subnet membership is enabled for the node.
|
||||
func (x NodeSubnetInfo) Enabled() bool {
|
||||
return !x.exit
|
||||
}
|
||||
|
||||
// SetEntryFlag sets the subnet entry flag.
|
||||
func (x *NodeSubnetInfo) SetEntryFlag(enters bool) {
|
||||
x.exit = !enters
|
||||
}
|
||||
|
||||
// ID returns identifier of the subnet.
|
||||
func (x NodeSubnetInfo) ID() *refs.SubnetID {
|
||||
return x.id
|
||||
}
|
||||
|
||||
// SetID sets identifier of the subnet.
|
||||
func (x *NodeSubnetInfo) SetID(id *refs.SubnetID) {
|
||||
x.id = id
|
||||
}
|
||||
|
||||
func subnetAttributeKey(id *refs.SubnetID) string {
|
||||
txt, _ := id.MarshalText() // never returns an error
|
||||
|
||||
return attrSubnetPrefix + string(txt)
|
||||
}
|
||||
|
||||
// WriteSubnetInfo writes NodeSubnetInfo to NodeInfo via attributes. NodeInfo must not be nil.
|
||||
//
|
||||
// Existing subnet attributes are expected to be key-unique, otherwise undefined behavior.
|
||||
//
|
||||
// Does not add (removes existing) attribute if node:
|
||||
// - disables non-zero subnet;
|
||||
// - enables zero subnet.
|
||||
//
|
||||
// Attribute key is calculated from ID using format `__SYSTEM__SUBNET_%s`.
|
||||
// Attribute Value is:
|
||||
// - `True` if node enters the subnet;
|
||||
// - `False`, otherwise.
|
||||
func WriteSubnetInfo(node *NodeInfo, info NodeSubnetInfo) {
|
||||
attrs := node.GetAttributes()
|
||||
|
||||
id := info.ID()
|
||||
enters := info.Enabled()
|
||||
|
||||
// calculate attribute key
|
||||
key := subnetAttributeKey(id)
|
||||
|
||||
if refs.IsZeroSubnet(id) == enters {
|
||||
for i := range attrs {
|
||||
if attrs[i].GetKey() == key {
|
||||
attrs = append(attrs[:i], attrs[i+1:]...)
|
||||
break // attributes are expected to be key-unique
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var val string
|
||||
|
||||
if enters {
|
||||
val = attrSubnetValEntry
|
||||
} else {
|
||||
val = attrSubnetValExit
|
||||
}
|
||||
|
||||
presented := false
|
||||
|
||||
for i := range attrs {
|
||||
if attrs[i].GetKey() == key {
|
||||
attrs[i].SetValue(val)
|
||||
presented = true
|
||||
}
|
||||
}
|
||||
|
||||
if !presented {
|
||||
index := len(attrs)
|
||||
attrs = append(attrs, Attribute{})
|
||||
attrs[index].SetKey(key)
|
||||
attrs[index].SetValue(val)
|
||||
}
|
||||
}
|
||||
|
||||
node.SetAttributes(attrs)
|
||||
}
|
||||
|
||||
// ErrRemoveSubnet is returned when a node needs to leave the 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.
|
||||
// Handler must not be nil.
|
||||
//
|
||||
// Subnet attributes are expected to be key-unique, otherwise undefined behavior.
|
||||
//
|
||||
// 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 the node is not included in any subnet by the end of the loop.
|
||||
func IterateSubnets(node *NodeInfo, f func(refs.SubnetID) error) error {
|
||||
attrs := node.GetAttributes()
|
||||
|
||||
var (
|
||||
err error
|
||||
id refs.SubnetID
|
||||
entries uint
|
||||
|
||||
zeroEntry = true
|
||||
)
|
||||
|
||||
for i := 0; i < len(attrs); i++ { // range must not be used because of attrs mutation in body
|
||||
key := attrs[i].GetKey()
|
||||
|
||||
// cut subnet ID string
|
||||
idTxt := strings.TrimPrefix(key, attrSubnetPrefix)
|
||||
if len(idTxt) == len(key) {
|
||||
idTxt = strings.TrimPrefix(key, attrSubnetPrefixNeoFS)
|
||||
if len(idTxt) == len(key) {
|
||||
// not a subnet attribute
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// check value
|
||||
val := attrs[i].GetValue()
|
||||
if val != attrSubnetValExit && val != attrSubnetValEntry {
|
||||
return fmt.Errorf("invalid attribute value: %s", val)
|
||||
}
|
||||
|
||||
// decode subnet ID
|
||||
if err = id.UnmarshalText([]byte(idTxt)); err != nil {
|
||||
return fmt.Errorf("invalid ID text: %w", err)
|
||||
}
|
||||
|
||||
// update status of zero subnet
|
||||
isZero := refs.IsZeroSubnet(&id)
|
||||
|
||||
if isZero {
|
||||
zeroEntry = val == attrSubnetValEntry
|
||||
}
|
||||
|
||||
// continue to process only the subnets to which the node belongs
|
||||
if val == attrSubnetValExit {
|
||||
continue
|
||||
}
|
||||
|
||||
// pass ID to the handler
|
||||
err = f(id)
|
||||
|
||||
isRemoveErr := errors.Is(err, ErrRemoveSubnet)
|
||||
|
||||
if err != nil && !isRemoveErr {
|
||||
return err
|
||||
}
|
||||
|
||||
if isRemoveErr {
|
||||
if isZero {
|
||||
// we can't remove attribute of zero subnet because it means entry
|
||||
attrs[i].SetValue(attrSubnetValExit)
|
||||
} else {
|
||||
// we can set False or remove attribute, latter is more memory/network efficient.
|
||||
attrs = append(attrs[:i], attrs[i+1:]...)
|
||||
i--
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
entries++
|
||||
}
|
||||
|
||||
if zeroEntry {
|
||||
// missing attribute of zero subnet equivalent to entry
|
||||
refs.MakeZeroSubnet(&id)
|
||||
|
||||
err = f(id)
|
||||
if err != nil {
|
||||
if !errors.Is(err, ErrRemoveSubnet) {
|
||||
return err
|
||||
}
|
||||
|
||||
// zero subnet should be clearly removed with False value
|
||||
index := len(attrs)
|
||||
attrs = append(attrs, Attribute{})
|
||||
attrs[index].SetKey(subnetAttributeKey(&id))
|
||||
attrs[index].SetValue(attrSubnetValExit)
|
||||
} else {
|
||||
entries++
|
||||
}
|
||||
}
|
||||
|
||||
if entries <= 0 {
|
||||
return errNoSubnets
|
||||
}
|
||||
|
||||
node.SetAttributes(attrs)
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,361 +0,0 @@
|
|||
package netmap_test
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap"
|
||||
netmaptest "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/test"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func subnetAttrKey(val string) string {
|
||||
return "__SYSTEM__SUBNET_" + val
|
||||
}
|
||||
|
||||
func assertSubnetAttrKey(t *testing.T, attr *netmap.Attribute, num uint32) {
|
||||
require.Equal(t, subnetAttrKey(strconv.FormatUint(uint64(num), 10)), attr.GetKey())
|
||||
}
|
||||
|
||||
func BenchmarkNodeAttributes(b *testing.B) {
|
||||
const size = 50
|
||||
|
||||
id := new(refs.SubnetID)
|
||||
id.SetValue(12)
|
||||
|
||||
attrs := make([]netmap.Attribute, size)
|
||||
for i := range attrs {
|
||||
if i == size/2 {
|
||||
attrs[i] = *netmaptest.GenerateAttribute(false)
|
||||
} else {
|
||||
data, err := id.MarshalText()
|
||||
require.NoError(b, err)
|
||||
|
||||
attrs[i].SetKey(subnetAttrKey(string(data)))
|
||||
attrs[i].SetValue("True")
|
||||
}
|
||||
}
|
||||
|
||||
var info netmap.NodeSubnetInfo
|
||||
info.SetID(id)
|
||||
info.SetEntryFlag(false)
|
||||
|
||||
node := new(netmap.NodeInfo)
|
||||
|
||||
// When using a single slice `StartTimer` overhead is comparable to the
|
||||
// function execution time, so we reduce this cost by updating slices in groups.
|
||||
const cacheSize = 1000
|
||||
a := make([][]netmap.Attribute, cacheSize)
|
||||
for i := range a {
|
||||
a[i] = make([]netmap.Attribute, size)
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if i%cacheSize == 0 {
|
||||
b.StopTimer()
|
||||
for j := range a {
|
||||
copy(a[j], attrs)
|
||||
}
|
||||
b.StartTimer()
|
||||
}
|
||||
node.SetAttributes(a[i%cacheSize])
|
||||
netmap.WriteSubnetInfo(node, info)
|
||||
if len(node.GetAttributes())+1 != len(attrs) {
|
||||
b.FailNow()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteSubnetInfo(t *testing.T) {
|
||||
t.Run("entry", func(t *testing.T) {
|
||||
t.Run("zero subnet", func(t *testing.T) {
|
||||
var (
|
||||
node netmap.NodeInfo
|
||||
info netmap.NodeSubnetInfo
|
||||
)
|
||||
|
||||
netmap.WriteSubnetInfo(&node, info)
|
||||
|
||||
// entry to zero subnet does not require an attribute
|
||||
attrs := node.GetAttributes()
|
||||
require.Empty(t, attrs)
|
||||
|
||||
// exit the subnet
|
||||
info.SetEntryFlag(false)
|
||||
|
||||
netmap.WriteSubnetInfo(&node, info)
|
||||
|
||||
// exit from zero subnet should be clearly reflected in attributes
|
||||
attrs = node.GetAttributes()
|
||||
require.Len(t, attrs, 1)
|
||||
|
||||
attr := &attrs[0]
|
||||
assertSubnetAttrKey(t, attr, 0)
|
||||
require.Equal(t, "False", attr.GetValue())
|
||||
|
||||
// again enter to zero subnet
|
||||
info.SetEntryFlag(true)
|
||||
|
||||
netmap.WriteSubnetInfo(&node, info)
|
||||
|
||||
// attribute should be removed
|
||||
attrs = node.GetAttributes()
|
||||
require.Empty(t, attrs)
|
||||
})
|
||||
|
||||
t.Run("non-zero subnet", func(t *testing.T) {
|
||||
var (
|
||||
node netmap.NodeInfo
|
||||
info netmap.NodeSubnetInfo
|
||||
id refs.SubnetID
|
||||
)
|
||||
|
||||
// create non-zero subnet ID
|
||||
const num = 15
|
||||
|
||||
id.SetValue(num)
|
||||
|
||||
// enter to the subnet
|
||||
info.SetID(&id)
|
||||
info.SetEntryFlag(true)
|
||||
|
||||
netmap.WriteSubnetInfo(&node, info)
|
||||
|
||||
// check attribute format
|
||||
attrs := node.GetAttributes()
|
||||
require.Len(t, attrs, 1)
|
||||
|
||||
attr := &attrs[0]
|
||||
assertSubnetAttrKey(t, attr, num)
|
||||
require.Equal(t, "True", attr.GetValue())
|
||||
|
||||
// again exit the subnet
|
||||
info.SetEntryFlag(false)
|
||||
|
||||
netmap.WriteSubnetInfo(&node, info)
|
||||
|
||||
// attribute should be removed
|
||||
attrs = node.GetAttributes()
|
||||
require.Empty(t, attrs)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestSubnets(t *testing.T) {
|
||||
t.Run("empty", func(t *testing.T) {
|
||||
var node netmap.NodeInfo
|
||||
|
||||
called := 0
|
||||
|
||||
err := netmap.IterateSubnets(&node, func(id refs.SubnetID) error {
|
||||
called++
|
||||
|
||||
require.True(t, refs.IsZeroSubnet(&id))
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.EqualValues(t, 1, called)
|
||||
})
|
||||
|
||||
t.Run("with correct attribute", func(t *testing.T) {
|
||||
var (
|
||||
node netmap.NodeInfo
|
||||
|
||||
attrEntry, attrExit netmap.Attribute
|
||||
)
|
||||
|
||||
const (
|
||||
numEntry = 13
|
||||
numExit = 14
|
||||
)
|
||||
|
||||
attrEntry.SetKey(subnetAttrKey(strconv.FormatUint(numEntry, 10)))
|
||||
attrEntry.SetValue("True")
|
||||
|
||||
attrExit.SetKey(subnetAttrKey(strconv.FormatUint(numExit, 10)))
|
||||
attrExit.SetValue("False")
|
||||
|
||||
attrs := []netmap.Attribute{attrEntry, attrEntry}
|
||||
|
||||
node.SetAttributes(attrs)
|
||||
|
||||
mCalledNums := make(map[uint32]struct{})
|
||||
|
||||
err := netmap.IterateSubnets(&node, func(id refs.SubnetID) error {
|
||||
mCalledNums[id.GetValue()] = struct{}{}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Len(t, mCalledNums, 2)
|
||||
|
||||
_, ok := mCalledNums[numEntry]
|
||||
require.True(t, ok)
|
||||
|
||||
_, ok = mCalledNums[numExit]
|
||||
require.False(t, ok)
|
||||
|
||||
_, ok = mCalledNums[0]
|
||||
require.True(t, ok)
|
||||
})
|
||||
|
||||
t.Run("with incorrect attribute", func(t *testing.T) {
|
||||
assertErr := func(attr netmap.Attribute) {
|
||||
var node netmap.NodeInfo
|
||||
|
||||
node.SetAttributes([]netmap.Attribute{attr})
|
||||
|
||||
require.Error(t, netmap.IterateSubnets(&node, func(refs.SubnetID) error {
|
||||
return nil
|
||||
}))
|
||||
}
|
||||
|
||||
t.Run("incorrect key", func(t *testing.T) {
|
||||
var attr netmap.Attribute
|
||||
|
||||
attr.SetKey(subnetAttrKey("one-two-three"))
|
||||
|
||||
assertErr(attr)
|
||||
})
|
||||
|
||||
t.Run("incorrect value", func(t *testing.T) {
|
||||
var attr netmap.Attribute
|
||||
|
||||
attr.SetKey(subnetAttrKey("1"))
|
||||
|
||||
for _, invalidVal := range []string{
|
||||
"",
|
||||
"Troo",
|
||||
"Fols",
|
||||
} {
|
||||
attr.SetValue(invalidVal)
|
||||
assertErr(attr)
|
||||
}
|
||||
|
||||
assertErr(attr)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("remove entry", func(t *testing.T) {
|
||||
t.Run("zero", func(t *testing.T) {
|
||||
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 {
|
||||
if refs.IsZeroSubnet(&id) {
|
||||
return netmap.ErrRemoveSubnet
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
attrs = node.GetAttributes()
|
||||
require.Len(t, attrs, 2)
|
||||
|
||||
found := false
|
||||
|
||||
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) {
|
||||
var (
|
||||
node netmap.NodeInfo
|
||||
attr netmap.Attribute
|
||||
)
|
||||
|
||||
attr.SetKey(subnetAttrKey("99"))
|
||||
attr.SetValue("True")
|
||||
|
||||
attrs := []netmap.Attribute{attr}
|
||||
node.SetAttributes(attrs)
|
||||
|
||||
err := netmap.IterateSubnets(&node, func(id refs.SubnetID) error {
|
||||
if !refs.IsZeroSubnet(&id) {
|
||||
return netmap.ErrRemoveSubnet
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
attrs = node.GetAttributes()
|
||||
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)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("zero subnet removal via attribute", func(t *testing.T) {
|
||||
var (
|
||||
node netmap.NodeInfo
|
||||
|
||||
attrZero, attrOther netmap.Attribute
|
||||
)
|
||||
|
||||
attrZero.SetKey(subnetAttrKey("0"))
|
||||
attrZero.SetValue("False")
|
||||
|
||||
attrOther.SetKey(subnetAttrKey("1"))
|
||||
attrOther.SetValue("True")
|
||||
|
||||
node.SetAttributes([]netmap.Attribute{attrZero, attrOther})
|
||||
|
||||
calledCount := 0
|
||||
|
||||
err := netmap.IterateSubnets(&node, func(id refs.SubnetID) error {
|
||||
require.False(t, refs.IsZeroSubnet(&id))
|
||||
calledCount++
|
||||
return nil
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.EqualValues(t, 1, calledCount)
|
||||
})
|
||||
}
|
|
@ -198,7 +198,6 @@ func (p *PlacementPolicy) ToGRPCMessage() grpc.Message {
|
|||
m.SetSelectors(SelectorsToGRPC(p.selectors))
|
||||
m.SetReplicas(ReplicasToGRPC(p.replicas))
|
||||
m.SetContainerBackupFactor(p.backupFactor)
|
||||
m.SetSubnetID(p.subnetID.ToGRPCMessage().(*refsGRPC.SubnetID))
|
||||
}
|
||||
|
||||
return m
|
||||
|
@ -227,20 +226,6 @@ func (p *PlacementPolicy) FromGRPCMessage(m grpc.Message) error {
|
|||
return err
|
||||
}
|
||||
|
||||
subnetID := v.GetSubnetId()
|
||||
if subnetID == nil {
|
||||
p.subnetID = nil
|
||||
} else {
|
||||
if p.subnetID == nil {
|
||||
p.subnetID = new(refs.SubnetID)
|
||||
}
|
||||
|
||||
err = p.subnetID.FromGRPCMessage(subnetID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
p.backupFactor = v.GetContainerBackupFactor()
|
||||
|
||||
return nil
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package netmap
|
||||
|
||||
import refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
|
||||
// SetReplicas of placement policy.
|
||||
func (m *PlacementPolicy) SetReplicas(v []*Replica) {
|
||||
m.Replicas = v
|
||||
|
@ -22,11 +20,6 @@ func (m *PlacementPolicy) SetFilters(v []*Filter) {
|
|||
m.Filters = v
|
||||
}
|
||||
|
||||
// SetSubnetID sets ID of subnet.
|
||||
func (m *PlacementPolicy) SetSubnetID(v *refs.SubnetID) {
|
||||
m.SubnetId = v
|
||||
}
|
||||
|
||||
// SetName of placement filter.
|
||||
func (m *Filter) SetName(v string) {
|
||||
m.Name = v
|
||||
|
|
BIN
netmap/grpc/types.pb.go
generated
BIN
netmap/grpc/types.pb.go
generated
Binary file not shown.
|
@ -26,7 +26,6 @@ const (
|
|||
backupPolicyField = 2
|
||||
selectorsPolicyField = 3
|
||||
filtersPolicyField = 4
|
||||
subnetIDPolicyField = 5
|
||||
|
||||
keyAttributeField = 1
|
||||
valueAttributeField = 2
|
||||
|
@ -167,8 +166,6 @@ func (p *PlacementPolicy) StableMarshal(buf []byte) []byte {
|
|||
offset += protoutil.NestedStructureMarshal(filtersPolicyField, buf[offset:], &p.filters[i])
|
||||
}
|
||||
|
||||
protoutil.NestedStructureMarshal(subnetIDPolicyField, buf[offset:], p.subnetID)
|
||||
|
||||
return buf
|
||||
}
|
||||
|
||||
|
@ -187,8 +184,6 @@ func (p *PlacementPolicy) StableSize() (size int) {
|
|||
size += protoutil.NestedStructureSize(filtersPolicyField, &p.filters[i])
|
||||
}
|
||||
|
||||
size += protoutil.NestedStructureSize(subnetIDPolicyField, p.subnetID)
|
||||
|
||||
return size
|
||||
}
|
||||
|
||||
|
|
|
@ -102,7 +102,6 @@ func GeneratePlacementPolicy(empty bool) *netmap.PlacementPolicy {
|
|||
m.SetFilters(GenerateFilters(false))
|
||||
m.SetSelectors(GenerateSelectors(false))
|
||||
m.SetReplicas(GenerateReplicas(false))
|
||||
m.SetSubnetID(refstest.GenerateSubnetID(false))
|
||||
}
|
||||
|
||||
return m
|
||||
|
|
|
@ -59,7 +59,6 @@ type PlacementPolicy struct {
|
|||
backupFactor uint32
|
||||
selectors []Selector
|
||||
filters []Filter
|
||||
subnetID *refs.SubnetID
|
||||
}
|
||||
|
||||
// Attribute of storage node.
|
||||
|
@ -302,14 +301,6 @@ func (p *PlacementPolicy) SetReplicas(replicas []Replica) {
|
|||
p.replicas = replicas
|
||||
}
|
||||
|
||||
func (p *PlacementPolicy) GetSubnetID() *refs.SubnetID {
|
||||
return p.subnetID
|
||||
}
|
||||
|
||||
func (p *PlacementPolicy) SetSubnetID(id *refs.SubnetID) {
|
||||
p.subnetID = id
|
||||
}
|
||||
|
||||
func (a *Attribute) GetKey() string {
|
||||
if a != nil {
|
||||
return a.key
|
||||
|
|
|
@ -266,31 +266,3 @@ func (s *Signature) FromGRPCMessage(m grpc.Message) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ToGRPCMessage forms refs.SubnetID message and returns it as grpc.Message.
|
||||
func (s *SubnetID) ToGRPCMessage() grpc.Message {
|
||||
var m *refs.SubnetID
|
||||
|
||||
if s != nil {
|
||||
m = new(refs.SubnetID)
|
||||
|
||||
m.SetValue(s.value)
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// FromGRPCMessage restores Info from grpc.Message.
|
||||
//
|
||||
// Supported types:
|
||||
// - refs.SubnetID.
|
||||
func (s *SubnetID) FromGRPCMessage(m grpc.Message) error {
|
||||
v, ok := m.(*refs.SubnetID)
|
||||
if !ok {
|
||||
return message.NewUnexpectedMessageType(m, v)
|
||||
}
|
||||
|
||||
s.value = v.GetValue()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -95,8 +95,3 @@ func (x *ChecksumType) FromString(s string) bool {
|
|||
|
||||
return ok
|
||||
}
|
||||
|
||||
// SetValue sets subnet identifier in a base-10 integer format.
|
||||
func (x *SubnetID) SetValue(v uint32) {
|
||||
x.Value = v
|
||||
}
|
||||
|
|
BIN
refs/grpc/types.pb.go
generated
BIN
refs/grpc/types.pb.go
generated
Binary file not shown.
|
@ -261,43 +261,3 @@ func (v *Version) StableSize() (size int) {
|
|||
func (v *Version) Unmarshal(data []byte) error {
|
||||
return message.Unmarshal(v, data, new(refs.Version))
|
||||
}
|
||||
|
||||
// SubnetID message field numbers
|
||||
const (
|
||||
_ = iota
|
||||
subnetIDValFNum
|
||||
)
|
||||
|
||||
// StableMarshal marshals SubnetID to NeoFS API V2 binary format (Protocol Buffers with direct field order).
|
||||
//
|
||||
// Returns a slice of recorded data. Data is written to the provided buffer if there is enough space.
|
||||
func (s *SubnetID) StableMarshal(buf []byte) []byte {
|
||||
if s == nil {
|
||||
return []byte{}
|
||||
}
|
||||
|
||||
if buf == nil {
|
||||
buf = make([]byte, s.StableSize())
|
||||
}
|
||||
|
||||
proto.Fixed32Marshal(subnetIDValFNum, buf, s.value)
|
||||
|
||||
return buf
|
||||
}
|
||||
|
||||
// StableSize returns the number of bytes required to write SubnetID in NeoFS API V2 binary format (see StableMarshal).
|
||||
func (s *SubnetID) StableSize() (size int) {
|
||||
if s != nil {
|
||||
size += proto.Fixed32Size(subnetIDValFNum, s.value)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Unmarshal unmarshals SubnetID from NeoFS API V2 binary format (see StableMarshal).
|
||||
// Must not be called on nil.
|
||||
//
|
||||
// Note: empty data corresponds to zero ID value or nil pointer to it.
|
||||
func (s *SubnetID) Unmarshal(data []byte) error {
|
||||
return message.Unmarshal(s, data, new(refs.SubnetID))
|
||||
}
|
||||
|
|
|
@ -17,6 +17,5 @@ func TestMessageConvert(t *testing.T) {
|
|||
func(empty bool) message.Message { return refstest.GenerateChecksum(empty) },
|
||||
func(empty bool) message.Message { return refstest.GenerateSignature(empty) },
|
||||
func(empty bool) message.Message { return refstest.GenerateVersion(empty) },
|
||||
func(empty bool) message.Message { return refstest.GenerateSubnetID(empty) },
|
||||
)
|
||||
}
|
||||
|
|
|
@ -106,13 +106,3 @@ func GenerateChecksum(empty bool) *refs.Checksum {
|
|||
|
||||
return m
|
||||
}
|
||||
|
||||
func GenerateSubnetID(empty bool) *refs.SubnetID {
|
||||
m := new(refs.SubnetID)
|
||||
|
||||
if !empty {
|
||||
m.SetValue(666)
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
package refs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type OwnerID struct {
|
||||
val []byte
|
||||
}
|
||||
|
@ -45,10 +40,6 @@ type Signature struct {
|
|||
scheme SignatureScheme
|
||||
}
|
||||
|
||||
type SubnetID struct {
|
||||
value uint32
|
||||
}
|
||||
|
||||
type Version struct {
|
||||
major, minor uint32
|
||||
}
|
||||
|
@ -178,56 +169,6 @@ func (s *Signature) SetScheme(scheme SignatureScheme) {
|
|||
s.scheme = scheme
|
||||
}
|
||||
|
||||
func (s *SubnetID) SetValue(id uint32) {
|
||||
s.value = id
|
||||
}
|
||||
|
||||
func (s *SubnetID) GetValue() uint32 {
|
||||
if s != nil {
|
||||
return s.value
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// MarshalText encodes SubnetID into text format according to NeoFS API V2 protocol:
|
||||
// value in base-10 integer string format.
|
||||
//
|
||||
// Implements encoding.TextMarshaler.
|
||||
func (s *SubnetID) MarshalText() ([]byte, error) {
|
||||
num := s.GetValue() // NPE safe, returns zero on nil (zero subnet)
|
||||
|
||||
return []byte(strconv.FormatUint(uint64(num), 10)), nil
|
||||
}
|
||||
|
||||
// UnmarshalText decodes SubnetID from the text according to NeoFS API V2 protocol:
|
||||
// should be base-10 integer string format with bitsize = 32.
|
||||
//
|
||||
// Returns strconv.ErrRange if integer overflows uint32.
|
||||
//
|
||||
// Must not be called on nil.
|
||||
//
|
||||
// Implements encoding.TextUnmarshaler.
|
||||
func (s *SubnetID) UnmarshalText(txt []byte) error {
|
||||
num, err := strconv.ParseUint(string(txt), 10, 32)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid numeric value: %w", err)
|
||||
}
|
||||
|
||||
s.value = uint32(num)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsZeroSubnet returns true iff the SubnetID refers to zero subnet.
|
||||
func IsZeroSubnet(id *SubnetID) bool {
|
||||
return id.GetValue() == 0
|
||||
}
|
||||
|
||||
// MakeZeroSubnet makes the SubnetID to refer to zero subnet.
|
||||
func MakeZeroSubnet(id *SubnetID) {
|
||||
id.SetValue(0)
|
||||
}
|
||||
|
||||
func (v *Version) GetMajor() uint32 {
|
||||
if v != nil {
|
||||
return v.major
|
||||
|
|
|
@ -1,72 +0,0 @@
|
|||
package refs_test
|
||||
|
||||
import (
|
||||
"math"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestZeroSubnet(t *testing.T) {
|
||||
id := new(refs.SubnetID)
|
||||
|
||||
require.True(t, refs.IsZeroSubnet(id))
|
||||
|
||||
id.SetValue(1)
|
||||
require.False(t, refs.IsZeroSubnet(id))
|
||||
|
||||
refs.MakeZeroSubnet(id)
|
||||
require.True(t, refs.IsZeroSubnet(id))
|
||||
}
|
||||
|
||||
func TestSubnetID_MarshalText(t *testing.T) {
|
||||
var id refs.SubnetID
|
||||
|
||||
const val = 15
|
||||
|
||||
id.SetValue(val)
|
||||
|
||||
txt, err := id.MarshalText()
|
||||
require.NoError(t, err)
|
||||
|
||||
res, err := strconv.ParseUint(string(txt), 10, 32)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.EqualValues(t, val, res)
|
||||
|
||||
t.Run("nil", func(t *testing.T) {
|
||||
var id *refs.SubnetID
|
||||
|
||||
txt, err := id.MarshalText()
|
||||
require.NoError(t, err)
|
||||
|
||||
res, err := strconv.ParseUint(string(txt), 10, 32)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Zero(t, res)
|
||||
})
|
||||
}
|
||||
|
||||
func TestSubnetID_UnmarshalText(t *testing.T) {
|
||||
const val = 15
|
||||
|
||||
str := strconv.FormatUint(val, 10)
|
||||
|
||||
var id refs.SubnetID
|
||||
|
||||
err := id.UnmarshalText([]byte(str))
|
||||
require.NoError(t, err)
|
||||
|
||||
require.EqualValues(t, val, id.GetValue())
|
||||
|
||||
t.Run("uint32 overflow", func(t *testing.T) {
|
||||
txt := strconv.FormatUint(math.MaxUint32+1, 10)
|
||||
|
||||
var id refs.SubnetID
|
||||
|
||||
err := id.UnmarshalText([]byte(txt))
|
||||
require.ErrorIs(t, err, strconv.ErrRange)
|
||||
})
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
package subnet_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/message"
|
||||
messagetest "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/message/test"
|
||||
subnettest "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/subnet/test"
|
||||
)
|
||||
|
||||
func TestMessageConvert(t *testing.T) {
|
||||
messagetest.TestRPCMessage(t,
|
||||
func(empty bool) message.Message { return subnettest.GenerateSubnetInfo(empty) },
|
||||
)
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
package subnet
|
||||
|
||||
import (
|
||||
refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
)
|
||||
|
||||
// SetID returns identifier of the subnet. Nil arg is equivalent to zero subnet ID.
|
||||
func (x *SubnetInfo) SetID(id *refs.SubnetID) {
|
||||
x.Id = id
|
||||
}
|
||||
|
||||
// SetOwner sets subnet owner's ID in NeoFS system.
|
||||
func (x *SubnetInfo) SetOwner(id *refs.OwnerID) {
|
||||
x.Owner = id
|
||||
}
|
BIN
subnet/grpc/types.pb.go
generated
BIN
subnet/grpc/types.pb.go
generated
Binary file not shown.
138
subnet/info.go
138
subnet/info.go
|
@ -1,138 +0,0 @@
|
|||
package subnet
|
||||
|
||||
import (
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
refsgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/message"
|
||||
subnet "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/subnet/grpc"
|
||||
protoutil "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto"
|
||||
)
|
||||
|
||||
// Info represents information about NeoFS subnet. Structure is compatible with NeoFS API V2 protocol.
|
||||
//
|
||||
// Zero value represents zero subnet w/o an owner.
|
||||
type Info struct {
|
||||
id *refs.SubnetID
|
||||
|
||||
owner *refs.OwnerID
|
||||
}
|
||||
|
||||
// ID returns identifier of the subnet. Nil return is equivalent to zero subnet ID.
|
||||
func (x *Info) ID() *refs.SubnetID {
|
||||
return x.id
|
||||
}
|
||||
|
||||
// SetID returns identifier of the subnet. Nil arg is equivalent to zero subnet ID.
|
||||
func (x *Info) SetID(id *refs.SubnetID) {
|
||||
x.id = id
|
||||
}
|
||||
|
||||
// Owner returns subnet owner's ID in NeoFS system.
|
||||
func (x *Info) Owner() *refs.OwnerID {
|
||||
return x.owner
|
||||
}
|
||||
|
||||
// SetOwner sets subnet owner's ID in NeoFS system.
|
||||
func (x *Info) SetOwner(id *refs.OwnerID) {
|
||||
x.owner = id
|
||||
}
|
||||
|
||||
// ToGRPCMessage forms subnet.SubnetInfo message and returns it as grpc.Message.
|
||||
func (x *Info) ToGRPCMessage() grpc.Message {
|
||||
var m *subnet.SubnetInfo
|
||||
|
||||
if x != nil {
|
||||
m = new(subnet.SubnetInfo)
|
||||
|
||||
m.SetID(x.id.ToGRPCMessage().(*refsgrpc.SubnetID))
|
||||
m.SetOwner(x.owner.ToGRPCMessage().(*refsgrpc.OwnerID))
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// FromGRPCMessage restores Info from grpc.Message.
|
||||
//
|
||||
// Supported types:
|
||||
// - subnet.SubnetInfo.
|
||||
func (x *Info) FromGRPCMessage(m grpc.Message) error {
|
||||
v, ok := m.(*subnet.SubnetInfo)
|
||||
if !ok {
|
||||
return message.NewUnexpectedMessageType(m, v)
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
id := v.GetId()
|
||||
if id == nil {
|
||||
x.id = nil
|
||||
} else {
|
||||
if x.id == nil {
|
||||
x.id = new(refs.SubnetID)
|
||||
}
|
||||
|
||||
err = x.id.FromGRPCMessage(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
ownerID := v.GetOwner()
|
||||
if ownerID == nil {
|
||||
x.owner = nil
|
||||
} else {
|
||||
if x.owner == nil {
|
||||
x.owner = new(refs.OwnerID)
|
||||
}
|
||||
|
||||
err = x.owner.FromGRPCMessage(ownerID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SubnetInfo message field numbers
|
||||
const (
|
||||
_ = iota
|
||||
subnetInfoIDFNum
|
||||
subnetInfoOwnerFNum
|
||||
)
|
||||
|
||||
// StableMarshal marshals Info to NeoFS API V2 binary format (Protocol Buffers with direct field order).
|
||||
//
|
||||
// Returns a slice of recorded data. Data is written to the provided buffer if there is enough space.
|
||||
func (x *Info) StableMarshal(buf []byte) []byte {
|
||||
if x == nil {
|
||||
return []byte{}
|
||||
}
|
||||
|
||||
if buf == nil {
|
||||
buf = make([]byte, x.StableSize())
|
||||
}
|
||||
|
||||
var offset int
|
||||
|
||||
offset += protoutil.NestedStructureMarshal(subnetInfoIDFNum, buf[offset:], x.id)
|
||||
protoutil.NestedStructureMarshal(subnetInfoOwnerFNum, buf[offset:], x.owner)
|
||||
|
||||
return buf
|
||||
}
|
||||
|
||||
// StableSize returns the number of bytes required to write Info in NeoFS API V2 binary format (see StableMarshal).
|
||||
func (x *Info) StableSize() (size int) {
|
||||
if x != nil {
|
||||
size += protoutil.NestedStructureSize(subnetInfoIDFNum, x.id)
|
||||
size += protoutil.NestedStructureSize(subnetInfoOwnerFNum, x.owner)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Unmarshal decodes Info from NeoFS API V2 binary format (see StableMarshal).
|
||||
func (x *Info) Unmarshal(data []byte) error {
|
||||
return message.Unmarshal(x, data, new(subnet.SubnetInfo))
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
package subnettest
|
||||
|
||||
import (
|
||||
refstest "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/test"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/subnet"
|
||||
)
|
||||
|
||||
func GenerateSubnetInfo(empty bool) *subnet.Info {
|
||||
m := new(subnet.Info)
|
||||
|
||||
if !empty {
|
||||
m.SetID(refstest.GenerateSubnetID(false))
|
||||
m.SetOwner(refstest.GenerateOwnerID(false))
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
Loading…
Reference in a new issue