[#129] v2: Add unified structure for NodeInfo

Signed-off-by: Alex Vanin <alexey@nspcc.ru>
This commit is contained in:
Alex Vanin 2020-09-01 10:46:20 +03:00 committed by Stanislav Bogatyrev
parent ac0d57cc9b
commit edd0004b93
4 changed files with 335 additions and 0 deletions

View file

@ -21,3 +21,73 @@ func PlacementPolicyFromGRPCMessage(m *netmap.PlacementPolicy) *PlacementPolicy
// TODO: fill me
return nil
}
func AttributeToGRPCMessage(a *Attribute) *netmap.NodeInfo_Attribute {
if a == nil {
return nil
}
m := new(netmap.NodeInfo_Attribute)
m.SetKey(a.GetKey())
m.SetValue(a.GetValue())
return m
}
func AttributeFromGRPCMessage(m *netmap.NodeInfo_Attribute) *Attribute {
if m == nil {
return nil
}
a := new(Attribute)
a.SetKey(m.GetKey())
a.SetValue(m.GetValue())
return a
}
func NodeInfoToGRPCMessage(n *NodeInfo) *netmap.NodeInfo {
if n == nil {
return nil
}
m := new(netmap.NodeInfo)
m.SetPublicKey(n.GetPublicKey())
m.SetAddress(n.GetAddress())
attr := n.GetAttributes()
attrMsg := make([]*netmap.NodeInfo_Attribute, 0, len(attr))
for i := range attr {
attrMsg = append(attrMsg, AttributeToGRPCMessage(attr[i]))
}
m.SetAttributes(attrMsg)
return m
}
func NodeInfoFromGRPCMessage(m *netmap.NodeInfo) *NodeInfo {
if m == nil {
return nil
}
a := new(NodeInfo)
a.SetPublicKey(m.GetPublicKey())
a.SetAddress(m.GetAddress())
attrMsg := m.GetAttributes()
attr := make([]*Attribute, 0, len(attrMsg))
for i := range attrMsg {
attr = append(attr, AttributeFromGRPCMessage(attrMsg[i]))
}
a.SetAttributes(attr)
return a
}

View file

@ -1,5 +1,18 @@
package netmap
import (
"github.com/nspcc-dev/neofs-api-go/util/proto"
)
const (
keyAttributeField = 1
valueAttributeField = 2
keyNodeInfoField = 1
addressNodeInfoField = 2
attributesNodeInfoField = 3
)
func (p *PlacementPolicy) StableMarshal(buf []byte) ([]byte, error) {
// todo: implement me
return nil, nil
@ -9,3 +22,97 @@ func (p *PlacementPolicy) StableSize() (size int) {
// todo: implement me
return 0
}
func (a *Attribute) StableMarshal(buf []byte) ([]byte, error) {
if a == nil {
return []byte{}, nil
}
if buf == nil {
buf = make([]byte, a.StableSize())
}
var (
offset, n int
err error
)
n, err = proto.StringMarshal(keyAttributeField, buf[offset:], a.key)
if err != nil {
return nil, err
}
offset += n
n, err = proto.StringMarshal(valueAttributeField, buf[offset:], a.value)
if err != nil {
return nil, err
}
return buf, nil
}
func (a *Attribute) StableSize() (size int) {
if a == nil {
return 0
}
size += proto.StringSize(keyAttributeField, a.key)
size += proto.StringSize(valueAttributeField, a.value)
return size
}
func (ni *NodeInfo) StableMarshal(buf []byte) ([]byte, error) {
if ni == nil {
return []byte{}, nil
}
if buf == nil {
buf = make([]byte, ni.StableSize())
}
var (
offset, n int
err error
)
n, err = proto.BytesMarshal(keyNodeInfoField, buf[offset:], ni.publicKey)
if err != nil {
return nil, err
}
offset += n
n, err = proto.StringMarshal(addressNodeInfoField, buf[offset:], ni.address)
if err != nil {
return nil, err
}
offset += n
for i := range ni.attributes {
n, err = proto.NestedStructureMarshal(attributesNodeInfoField, buf[offset:], ni.attributes[i])
if err != nil {
return nil, err
}
offset += n
}
return buf, nil
}
func (ni *NodeInfo) StableSize() (size int) {
if ni == nil {
return 0
}
size += proto.BytesSize(keyNodeInfoField, ni.publicKey)
size += proto.StringSize(addressNodeInfoField, ni.address)
for i := range ni.attributes {
size += proto.NestedStructureSize(attributesNodeInfoField, ni.attributes[i])
}
return size
}

66
v2/netmap/marshal_test.go Normal file
View file

@ -0,0 +1,66 @@
package netmap_test
import (
"strconv"
"testing"
"github.com/nspcc-dev/neofs-api-go/v2/netmap"
grpc "github.com/nspcc-dev/neofs-api-go/v2/netmap/grpc"
"github.com/stretchr/testify/require"
)
func TestAttribute_StableMarshal(t *testing.T) {
from := generateAttribute("key", "value")
transport := new(grpc.NodeInfo_Attribute)
t.Run("non empty", func(t *testing.T) {
wire, err := from.StableMarshal(nil)
require.NoError(t, err)
err = transport.Unmarshal(wire)
require.NoError(t, err)
to := netmap.AttributeFromGRPCMessage(transport)
require.Equal(t, from, to)
})
}
func TestNodeInfo(t *testing.T) {
from := generateNodeInfo("publicKey", "/multi/addr", 10)
transport := new(grpc.NodeInfo)
t.Run("non empty", func(t *testing.T) {
wire, err := from.StableMarshal(nil)
require.NoError(t, err)
err = transport.Unmarshal(wire)
require.NoError(t, err)
to := netmap.NodeInfoFromGRPCMessage(transport)
require.Equal(t, from, to)
})
}
func generateAttribute(k, v string) *netmap.Attribute {
attr := new(netmap.Attribute)
attr.SetKey(k)
attr.SetValue(v)
return attr
}
func generateNodeInfo(key, addr string, n int) *netmap.NodeInfo {
nodeInfo := new(netmap.NodeInfo)
nodeInfo.SetPublicKey([]byte(key))
nodeInfo.SetAddress(addr)
attrs := make([]*netmap.Attribute, n)
for i := 0; i < n; i++ {
j := strconv.Itoa(n)
attrs[i] = generateAttribute("key"+j, "value"+j)
}
nodeInfo.SetAttributes(attrs)
return nodeInfo
}

View file

@ -3,3 +3,95 @@ package netmap
type PlacementPolicy struct {
// TODO: fill me
}
// Attribute of storage node.
type Attribute struct {
key string
value string
}
// NodeInfo of storage node.
type NodeInfo struct {
publicKey []byte
address string
attributes []*Attribute
}
// NodeState of storage node.
type NodeState uint32
const (
Unspecified NodeState = iota
Online
Offline
)
func (a *Attribute) GetKey() string {
if a != nil {
return a.key
}
return ""
}
func (a *Attribute) SetKey(v string) {
if a != nil {
a.key = v
}
}
func (a *Attribute) GetValue() string {
if a != nil {
return a.value
}
return ""
}
func (a *Attribute) SetValue(v string) {
if a != nil {
a.value = v
}
}
func (ni *NodeInfo) GetPublicKey() []byte {
if ni != nil {
return ni.publicKey
}
return nil
}
func (ni *NodeInfo) SetPublicKey(v []byte) {
if ni != nil {
ni.publicKey = v
}
}
func (ni *NodeInfo) GetAddress() string {
if ni != nil {
return ni.address
}
return ""
}
func (ni *NodeInfo) SetAddress(v string) {
if ni != nil {
ni.address = v
}
}
func (ni *NodeInfo) GetAttributes() []*Attribute {
if ni != nil {
return ni.attributes
}
return nil
}
func (ni *NodeInfo) SetAttributes(v []*Attribute) {
if ni != nil {
ni.attributes = v
}
}