diff --git a/container/attributes.go b/container/attributes.go index 1d7c94a..12277ed 100644 --- a/container/attributes.go +++ b/container/attributes.go @@ -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" diff --git a/container/grpc/types.pb.go b/container/grpc/types.pb.go index 7f0cc1b..0cd53eb 100644 Binary files a/container/grpc/types.pb.go and b/container/grpc/types.pb.go differ diff --git a/netmap/attributes.go b/netmap/attributes.go deleted file mode 100644 index 205376b..0000000 --- a/netmap/attributes.go +++ /dev/null @@ -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 -} diff --git a/netmap/attributes_test.go b/netmap/attributes_test.go deleted file mode 100644 index 1a340bd..0000000 --- a/netmap/attributes_test.go +++ /dev/null @@ -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) - }) -} diff --git a/netmap/convert.go b/netmap/convert.go index cc20d36..6bb1525 100644 --- a/netmap/convert.go +++ b/netmap/convert.go @@ -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 diff --git a/netmap/grpc/types.go b/netmap/grpc/types.go index d0bf41a..f312bbb 100644 --- a/netmap/grpc/types.go +++ b/netmap/grpc/types.go @@ -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 diff --git a/netmap/grpc/types.pb.go b/netmap/grpc/types.pb.go index 276e648..f1d5ef0 100644 Binary files a/netmap/grpc/types.pb.go and b/netmap/grpc/types.pb.go differ diff --git a/netmap/marshal.go b/netmap/marshal.go index e08d6f0..5c8cf35 100644 --- a/netmap/marshal.go +++ b/netmap/marshal.go @@ -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 } diff --git a/netmap/test/generate.go b/netmap/test/generate.go index 30e200e..8889bab 100644 --- a/netmap/test/generate.go +++ b/netmap/test/generate.go @@ -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 diff --git a/netmap/types.go b/netmap/types.go index c878184..27fc2ff 100644 --- a/netmap/types.go +++ b/netmap/types.go @@ -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 diff --git a/refs/convert.go b/refs/convert.go index 028bd6a..b2c353c 100644 --- a/refs/convert.go +++ b/refs/convert.go @@ -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 -} diff --git a/refs/grpc/types.go b/refs/grpc/types.go index 0cf7368..843a2ee 100644 --- a/refs/grpc/types.go +++ b/refs/grpc/types.go @@ -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 -} diff --git a/refs/grpc/types.pb.go b/refs/grpc/types.pb.go index 0d6b671..f16583b 100644 Binary files a/refs/grpc/types.pb.go and b/refs/grpc/types.pb.go differ diff --git a/refs/marshal.go b/refs/marshal.go index 14b0f8c..0382190 100644 --- a/refs/marshal.go +++ b/refs/marshal.go @@ -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)) -} diff --git a/refs/message_test.go b/refs/message_test.go index ba36434..69f2242 100644 --- a/refs/message_test.go +++ b/refs/message_test.go @@ -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) }, ) } diff --git a/refs/test/generate.go b/refs/test/generate.go index cce64a8..6217a96 100644 --- a/refs/test/generate.go +++ b/refs/test/generate.go @@ -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 -} diff --git a/refs/types.go b/refs/types.go index 2d4fec7..d8f0d9b 100644 --- a/refs/types.go +++ b/refs/types.go @@ -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 diff --git a/refs/types_test.go b/refs/types_test.go deleted file mode 100644 index 68d8fd7..0000000 --- a/refs/types_test.go +++ /dev/null @@ -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) - }) -} diff --git a/subnet/encoding_test.go b/subnet/encoding_test.go deleted file mode 100644 index 0a1fea1..0000000 --- a/subnet/encoding_test.go +++ /dev/null @@ -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) }, - ) -} diff --git a/subnet/grpc/types.go b/subnet/grpc/types.go deleted file mode 100644 index 3196c5a..0000000 --- a/subnet/grpc/types.go +++ /dev/null @@ -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 -} diff --git a/subnet/grpc/types.pb.go b/subnet/grpc/types.pb.go deleted file mode 100644 index 032ba6c..0000000 Binary files a/subnet/grpc/types.pb.go and /dev/null differ diff --git a/subnet/info.go b/subnet/info.go deleted file mode 100644 index 2e1e94c..0000000 --- a/subnet/info.go +++ /dev/null @@ -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)) -} diff --git a/subnet/test/generate.go b/subnet/test/generate.go deleted file mode 100644 index 214ac7b..0000000 --- a/subnet/test/generate.go +++ /dev/null @@ -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 -}