diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index e7d3271b1..7d4831bce 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -282,11 +282,62 @@ func initNetmapState(c *cfg) { c.handleLocalNodeInfo(ni) } -func sameNodeInfo(a, b *netmapSDK.NodeInfo) bool { - // Suboptimal, but we do this once on the node startup. - rawA := a.Marshal() - rawB := b.Marshal() - return bytes.Equal(rawA, rawB) +func needsUpdate(local, remote *netmapSDK.NodeInfo) bool { + return bytes.Equal(local.PublicKey(), remote.PublicKey()) && equalEndpoints(local, remote) && equalAttributes(local, remote) +} + +func equalAttributes(local, remote *netmapSDK.NodeInfo) bool { + asA := make(map[string]string) + local.IterateAttributes(func(k, v string) { + asA[k] = v + }) + + allMatched := true + count := 0 + remote.IterateAttributes(func(k, vb string) { + // IR adds new attributes derived from the locode, they should be skipped. + if isLocodeAttribute(k) { + return + } + if va, ok := asA[k]; !ok || va != vb { + allMatched = false + return + } + count++ + }) + return allMatched && count == len(asA) +} + +func isLocodeAttribute(k string) bool { + // See https://git.frostfs.info/TrueCloudLab/frostfs-api/src/branch/master/netmap/types.proto#L171 + switch k { + case "Continent", "Country", "CountryCode", "Location", "SubDiv", "SubDivCode": + return true + default: + return false + } +} + +func equalEndpoints(a, b *netmapSDK.NodeInfo) bool { + var esA, esB []string + a.IterateNetworkEndpoints(func(e string) bool { + esA = append(esA, e) + return false + }) + b.IterateNetworkEndpoints(func(e string) bool { + esB = append(esB, e) + return false + }) + + if len(esA) != len(esB) { + return false + } + for i := range esA { + if esA[i] != esB[i] { + return false + } + } + return true } func nodeState(ni *netmapSDK.NodeInfo) string { @@ -314,7 +365,7 @@ func (c *cfg) netmapInitLocalNodeState(epoch uint64) (*netmapSDK.NodeInfo, bool, for i := range nmNodes { if bytes.Equal(nmNodes[i].PublicKey(), c.binPublicKey) { candidate = &nmNodes[i] - alreadyBootstraped = candidate.IsOnline() && sameNodeInfo(&c.cfgNodeInfo.localInfo, candidate) + alreadyBootstraped = candidate.IsOnline() && needsUpdate(&c.cfgNodeInfo.localInfo, candidate) break } } diff --git a/go.mod b/go.mod index 89f437216..c911b151e 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.0 git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.0 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230911122224-ac8fc6d4400c + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230915114754-555ccc63b255 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 github.com/cheggaaa/pb v1.0.29 diff --git a/go.sum b/go.sum index 5bcd5e428..0df98fe6d 100644 --- a/go.sum +++ b/go.sum @@ -393,8 +393,8 @@ git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSV git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6 h1:aGQ6QaAnTerQ5Dq5b2/f9DUQtSqPkZZ/bkMx/HKuLCo= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6/go.mod h1:W8Nn08/l6aQ7UlIbpF7FsQou7TVpcRD1ZT1KG4TrFhE= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230911122224-ac8fc6d4400c h1:gD+dj5IZx9jlniDu8TlLQdRGCd8KIOzYjjdDd1KcVdI= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230911122224-ac8fc6d4400c/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230915114754-555ccc63b255 h1:9oJs98TOC5MOOwnhHAiynbptBYAQOQ9okgK/V1sZ8CE= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230915114754-555ccc63b255/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= diff --git a/pkg/morph/subscriber/subscriber.go b/pkg/morph/subscriber/subscriber.go index c2d8494fa..afeed20b5 100644 --- a/pkg/morph/subscriber/subscriber.go +++ b/pkg/morph/subscriber/subscriber.go @@ -60,9 +60,16 @@ type ( // Params is a group of Subscriber constructor parameters. Params struct { - Log *logger.Logger - StartFromBlock uint32 - Client *client.Client + Log *logger.Logger + StartFromBlock uint32 + Client *client.Client + NotificationsConfig NotificationsConfig + } + + NotificationsConfig struct { + NotificationChannelSize uint32 + BlockChannelSize uint32 + NotaryRequestChannelSize uint32 } ) @@ -169,7 +176,7 @@ func New(ctx context.Context, p *Params) (Subscriber, error) { blockChan: make(chan *block.Block), notaryChan: make(chan *result.NotaryRequestEvent), - current: newSubChannels(), + current: newSubChannels(p.NotificationsConfig), subscribedEvents: make(map[util.Uint160]bool), subscribedNotaryEvents: make(map[util.Uint160]bool), @@ -259,7 +266,14 @@ func (s *subscriber) switchEndpoint(ctx context.Context, finishCh chan<- bool) ( cliCh := s.client.NotificationChannel() s.Lock() - chs := newSubChannels() + + param := NotificationsConfig{ + NotificationChannelSize: uint32(cap(s.current.NotifyChan)), + BlockChannelSize: uint32(cap(s.current.BlockChan)), + NotaryRequestChannelSize: uint32(cap(s.current.NotaryChan)), + } + + chs := newSubChannels(param) go func() { finishCh <- s.restoreSubscriptions(chs.NotifyChan, chs.BlockChan, chs.NotaryChan) }() @@ -270,11 +284,11 @@ func (s *subscriber) switchEndpoint(ctx context.Context, finishCh chan<- bool) ( return true, cliCh } -func newSubChannels() subChannels { +func newSubChannels(param NotificationsConfig) subChannels { return subChannels{ - NotifyChan: make(chan *state.ContainedNotificationEvent), - BlockChan: make(chan *block.Block), - NotaryChan: make(chan *result.NotaryRequestEvent), + NotifyChan: make(chan *state.ContainedNotificationEvent, param.NotificationChannelSize), + BlockChan: make(chan *block.Block, param.BlockChannelSize), + NotaryChan: make(chan *result.NotaryRequestEvent, param.NotaryRequestChannelSize), } }