Skip to content

Commit

Permalink
feat/Move locode attrs expansion on SN side (nspcc-dev#2648)
Browse files Browse the repository at this point in the history
  • Loading branch information
roman-khimov authored Nov 24, 2023
2 parents 42cf34f + f8f0817 commit bea2ad3
Show file tree
Hide file tree
Showing 18 changed files with 214 additions and 110 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Changelog for NeoFS Node
- New optimized SDK version is integrated (#2622)
- IR uses internal LOCODE DB from Go package (#2610)
- Contract group for the committee is no longer registered/used in the Sidechain auto-deployment (#2642)
- IR does not change SNs' attributes, SNs expand UN/LOCODE attributes do it themselves (#2612)
- The priority of metrics service is increased (#2428)
- The priority of running control service is maximized (#2585)

Expand Down
85 changes: 85 additions & 0 deletions cmd/neofs-node/attributes.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package main

import (
"fmt"

"github.com/nspcc-dev/locode-db/pkg/locodedb"
nodeconfig "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/node"
"github.com/nspcc-dev/neofs-node/pkg/util/attributes"
"go.uber.org/zap"
)

func parseAttributes(c *cfg) {
Expand All @@ -11,4 +15,85 @@ func parseAttributes(c *cfg) {
}

fatalOnErr(attributes.ReadNodeAttributes(&c.cfgNodeInfo.localInfo, nodeconfig.Attributes(c.appCfg)))

// expand UN/LOCODE attribute if any found; keep user's attributes
// if any conflicts appear

locAttr := c.cfgNodeInfo.localInfo.LOCODE()
if locAttr == "" {
return
}

record, err := getRecord(locAttr)
if err != nil {
fatalOnErr(fmt.Errorf("could not get locode record from DB: %w", err))
}

countryCode := locAttr[:locodedb.CountryCodeLen]
n := &c.cfgNodeInfo.localInfo

fromUser := n.CountryCode()
if fromUser != "" && fromUser != countryCode {
c.log.Warn("locode attribute mismatch, configuration value kept: country code",
zap.String("configuration_value", fromUser),
zap.String("database_value", countryCode))
} else {
setIfNotEmpty(n.SetCountryCode, countryCode)
}

fromUser = n.CountryName()
if fromUser != "" && fromUser != record.Country {
c.log.Warn("locode attribute mismatch, configuration value kept: country name",
zap.String("configuration_value", fromUser),
zap.String("database_value", record.Country))
} else {
setIfNotEmpty(n.SetCountryName, record.Country)
}

fromUser = n.LocationName()
if fromUser != "" && fromUser != record.Location {
c.log.Warn("locode attribute mismatch, configuration value kept: location name",
zap.String("configuration_value", fromUser),
zap.String("database_value", record.Location))
} else {
setIfNotEmpty(n.SetLocationName, record.Location)
}

fromUser = n.ContinentName()
if fromUser != "" && fromUser != record.Cont.String() {
c.log.Warn("locode attribute mismatch, configuration value kept: continent",
zap.String("configuration_value", fromUser),
zap.String("database_value", record.Cont.String()))
} else {
setIfNotEmpty(n.SetContinentName, record.Cont.String())
}

fromUser = n.SubdivisionCode()
if fromUser != "" && fromUser != record.SubDivCode {
c.log.Warn("locode attribute mismatch, configuration value kept: subdivision code",
zap.String("configuration_value", fromUser),
zap.String("database_value", record.SubDivCode))
} else {
setIfNotEmpty(n.SetSubdivisionCode, record.SubDivCode)
}

fromUser = n.SubdivisionName()
if fromUser != "" && fromUser != record.SubDivName {
c.log.Warn("locode attribute mismatch, configuration value kept: subdivision name",
zap.String("configuration_value", fromUser),
zap.String("database_value", record.SubDivName))
} else {
setIfNotEmpty(n.SetSubdivisionName, record.SubDivName)
}
}

func getRecord(lc string) (locodedb.Record, error) {
rec, err := locodedb.Get(lc)
return rec, err
}

func setIfNotEmpty(setter func(string), value string) {
if value != "" {
setter(value)
}
}
24 changes: 5 additions & 19 deletions cmd/neofs-node/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ type cfgNetmap struct {
}

type cfgNodeInfo struct {
// values from config
// values from config; NOT MODIFY AFTER APP INITIALIZATION
localInfo netmap.NodeInfo
}

Expand Down Expand Up @@ -822,21 +822,15 @@ func initObjectPool(cfg *config.Config) (pool cfgObjectRoutines) {

func (c *cfg) LocalNodeInfo() (*netmapV2.NodeInfo, error) {
var res netmapV2.NodeInfo

ni, ok := c.cfgNetmap.state.getNodeInfo()
if ok {
ni.WriteToV2(&res)
} else {
c.cfgNodeInfo.localInfo.WriteToV2(&res)
}
c.cfgNodeInfo.localInfo.WriteToV2(&res)

return &res, nil
}

// handleLocalNodeInfo rewrites local node info from the NeoFS network map.
// handleLocalNodeInfoFromNetwork rewrites cached node info from the NeoFS network map.
// Called with nil when storage node is outside the NeoFS network map
// (before entering the network and after leaving it).
func (c *cfg) handleLocalNodeInfo(ni *netmap.NodeInfo) {
func (c *cfg) handleLocalNodeInfoFromNetwork(ni *netmap.NodeInfo) {
c.cfgNetmap.state.setNodeInfo(ni)
c.localNodeInNetmap.Store(ni != nil)
}
Expand All @@ -845,15 +839,7 @@ func (c *cfg) handleLocalNodeInfo(ni *netmap.NodeInfo) {
// with the binary-encoded information from the current node's configuration.
// The state is set using the provided setter which MUST NOT be nil.
func (c *cfg) bootstrapWithState(stateSetter func(*netmap.NodeInfo)) error {
var ni netmap.NodeInfo
if niAtomic := c.cfgNetmap.state.nodeInfo.Load(); niAtomic != nil {
// node has already been bootstrapped successfully
ni = niAtomic.(netmap.NodeInfo)
} else {
// unknown network state
ni = c.cfgNodeInfo.localInfo
}

ni := c.cfgNodeInfo.localInfo
stateSetter(&ni)

prm := nmClient.AddPeerPrm{}
Expand Down
17 changes: 5 additions & 12 deletions cmd/neofs-node/netmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,19 +117,12 @@ func nodeKeyFromNetmap(c *cfg) []byte {
}

func (c *cfg) iterateNetworkAddresses(f func(string) bool) {
ni, ok := c.cfgNetmap.state.getNodeInfo()
if ok {
ni.IterateNetworkEndpoints(f)
}
ni := c.cfgNodeInfo.localInfo
ni.IterateNetworkEndpoints(f)
}

func (c *cfg) addressNum() int {
ni, ok := c.cfgNetmap.state.getNodeInfo()
if ok {
return ni.NumberOfNetworkEndpoints()
}

return 0
return c.cfgNodeInfo.localInfo.NumberOfNetworkEndpoints()
}

func initNetmapService(c *cfg) {
Expand Down Expand Up @@ -201,7 +194,7 @@ func initNetmapService(c *cfg) {
return
}

c.handleLocalNodeInfo(ni)
c.handleLocalNodeInfoFromNetwork(ni)
})

addNewEpochAsyncNotificationHandler(c, func(ev event.Event) {
Expand Down Expand Up @@ -285,7 +278,7 @@ func getNetworkState(c *cfg) (uint64, *netmapSDK.NodeInfo, error) {
func updateLocalState(c *cfg, epoch uint64, ni *netmapSDK.NodeInfo) {
c.cfgNetmap.state.setCurrentEpoch(epoch)
c.cfgNetmap.startEpoch = epoch
c.handleLocalNodeInfo(ni)
c.handleLocalNodeInfoFromNetwork(ni)
}

func (c *cfg) netmapLocalNodeState(epoch uint64) (*netmapSDK.NodeInfo, error) {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ require (
github.com/nspcc-dev/neo-go v0.103.1
github.com/nspcc-dev/neofs-api-go/v2 v2.14.0
github.com/nspcc-dev/neofs-contract v0.18.0
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11.0.20231113180740-3b24af0410c0
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11.0.20231121125354-d72d76ccb0ba
github.com/nspcc-dev/tzhash v1.7.1
github.com/olekukonko/tablewriter v0.0.5
github.com/panjf2000/ants/v2 v2.8.2
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,8 @@ github.com/nspcc-dev/neofs-contract v0.18.0 h1:9g50b16s0mQFFskG93yRSWh4KL7yYOW+x
github.com/nspcc-dev/neofs-contract v0.18.0/go.mod h1:UQr1rUjg0eibLwJd6vfsJJEUBnmRysCg8XQd1HYiS2w=
github.com/nspcc-dev/neofs-crypto v0.4.0 h1:5LlrUAM5O0k1+sH/sktBtrgfWtq1pgpDs09fZo+KYi4=
github.com/nspcc-dev/neofs-crypto v0.4.0/go.mod h1:6XJ8kbXgOfevbI2WMruOtI+qUJXNwSGM/E9eClXxPHs=
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11.0.20231113180740-3b24af0410c0 h1:y24pnVwDLaBAyh8fFcptAvtVfVDay/5jONgtO+cWZfI=
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11.0.20231113180740-3b24af0410c0/go.mod h1:6ok9MU40TP0xAVfzisIg4KP+qhP670hra0mKpIGlWT8=
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11.0.20231121125354-d72d76ccb0ba h1:dQDBBqmT2rlJGgkeeF3UurB3VgG7buMHDHcz5UQ3bro=
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11.0.20231121125354-d72d76ccb0ba/go.mod h1:2PKUuH7kQaAmQ/USBgmiD/k08ssnSvayor6JAFhrC1c=
github.com/nspcc-dev/rfc6979 v0.2.0 h1:3e1WNxrN60/6N0DW7+UYisLeZJyfqZTNOjeV/toYvOE=
github.com/nspcc-dev/rfc6979 v0.2.0/go.mod h1:exhIh1PdpDC5vQmyEsGvc4YDM/lyQp/452QxGq/UEso=
github.com/nspcc-dev/tzhash v1.7.1 h1:6zmexLqdTF/ssbUAh7XJS7RxgKWaw28kdNpE/4UFdEU=
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import (
// the Validator is immediately ready to work through API.
type Validator struct{}

func (v Validator) VerifyAndUpdate(nodeInfo *netmap.NodeInfo) error {
func (v Validator) Verify(nodeInfo netmap.NodeInfo) error {
var results []*client.ResEndpointInfo
var err error

Expand Down Expand Up @@ -53,7 +53,7 @@ func (v Validator) VerifyAndUpdate(nodeInfo *netmap.NodeInfo) error {
}

for _, res := range results {
err = compareNodeInfos(*nodeInfo, res.NodeInfo())
err = compareNodeInfos(nodeInfo, res.NodeInfo())
if err != nil {
return fmt.Errorf("`EndpointInfo` RPC call result differs: %w", err)
}
Expand Down
41 changes: 26 additions & 15 deletions pkg/innerring/processors/netmap/nodevalidation/locode/calls.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,50 @@ package locode
import (
"fmt"

"github.com/nspcc-dev/locode-db/pkg/locodedb"
"github.com/nspcc-dev/neofs-sdk-go/netmap"
)

// VerifyAndUpdate validates UN-LOCODE attribute of n
// Verify validates UN-LOCODE attribute of n
// and adds a group of related attributes.
//
// If n contains at least one of the LOCODE-derived attributes,
// an error is returned.
//
// If n contains UN-LOCODE attribute and its value does not
// match the UN/LOCODE format, an error is returned.
//
// UN-LOCODE attribute remains untouched.
func (v *Validator) VerifyAndUpdate(n *netmap.NodeInfo) error {
if n.LOCODE() == "" {
func (v *Validator) Verify(n netmap.NodeInfo) error {
lAttr := n.LOCODE()
if lAttr == "" {
return nil
}
key, record, err := v.Get(n.LOCODE())
record, err := getRecord(lAttr)
if err != nil {
return fmt.Errorf("could not get locode record from DB: %w", err)
}

n.SetCountryCode(key.CountryCode().String())
n.SetCountryName(record.Country)
n.SetLocationName(record.Location)
n.SetContinentName(record.Cont.String())
if subDivCode := record.SubDivCode; subDivCode != "" {
n.SetSubdivisionCode(subDivCode)
if want, got := lAttr[:locodedb.CountryCodeLen], n.CountryCode(); want != got {
return wrongLocodeAttrErr("country code", want, got)
}

if subDivName := record.SubDivName; subDivName != "" {
n.SetSubdivisionName(subDivName)
if want, got := record.Country, n.CountryName(); want != got {
return wrongLocodeAttrErr("country name", want, got)
}
if want, got := record.Location, n.LocationName(); want != got {
return wrongLocodeAttrErr("location", want, got)
}
if want, got := record.Cont.String(), n.ContinentName(); want != got {
return wrongLocodeAttrErr("continent", want, got)
}
if want, got := record.SubDivCode, n.SubdivisionCode(); want != got {
return wrongLocodeAttrErr("subdivision code", want, got)
}
if want, got := record.SubDivName, n.SubdivisionName(); want != got {
return wrongLocodeAttrErr("subdivision name", want, got)
}

return nil
}

func wrongLocodeAttrErr(attrName, want, got string) error {
return fmt.Errorf("wrong %q attribute value: want '%q', got '%q'", attrName, want, got)
}
Loading

0 comments on commit bea2ad3

Please sign in to comment.