diff --git a/cmd/internal/cmdprinter/netmap.go b/cmd/internal/cmdprinter/netmap.go index 18694b803f..67407e7040 100644 --- a/cmd/internal/cmdprinter/netmap.go +++ b/cmd/internal/cmdprinter/netmap.go @@ -26,9 +26,9 @@ func PrettyPrintNodeInfo(cmd *cobra.Command, node netmap.NodeInfo, cmd.Printf("%sNode %d: %s %s ", indent, index+1, hex.EncodeToString(node.PublicKey()), strState) - netmap.IterateNetworkEndpoints(node, func(endpoint string) { + for endpoint := range func(f func(string) bool) { node.IterateNetworkEndpoints(func(s string) bool { return !f(s) }) } { cmd.Printf("%s ", endpoint) - }) + } cmd.Println() if !short { diff --git a/cmd/neofs-cli/modules/netmap/nodeinfo.go b/cmd/neofs-cli/modules/netmap/nodeinfo.go index c6d3f9b52e..cdf45afaef 100644 --- a/cmd/neofs-cli/modules/netmap/nodeinfo.go +++ b/cmd/neofs-cli/modules/netmap/nodeinfo.go @@ -69,9 +69,9 @@ func prettyPrintNodeInfo(cmd *cobra.Command, i netmap.NodeInfo) { cmd.Println("state:", stateWord) - netmap.IterateNetworkEndpoints(i, func(s string) { + for s := range func(f func(string) bool) { i.IterateNetworkEndpoints(func(s string) bool { return !f(s) }) } { cmd.Println("address:", s) - }) + } i.IterateAttributes(func(key, value string) { cmd.Printf("attribute: %s=%s\n", key, value) diff --git a/cmd/neofs-node/config/node/config.go b/cmd/neofs-node/config/node/config.go index 6bacbb5d25..d12532e7d7 100644 --- a/cmd/neofs-node/config/node/config.go +++ b/cmd/neofs-node/config/node/config.go @@ -57,7 +57,7 @@ type stringAddressGroup []string func (x stringAddressGroup) IterateAddresses(f func(string) bool) { for i := range x { - if f(x[i]) { + if !f(x[i]) { break } } diff --git a/cmd/neofs-node/config/node/config_test.go b/cmd/neofs-node/config/node/config_test.go index 8312f9174c..1668cb2be6 100644 --- a/cmd/neofs-node/config/node/config_test.go +++ b/cmd/neofs-node/config/node/config_test.go @@ -1,12 +1,12 @@ package nodeconfig import ( + "slices" "testing" "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config" configtest "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/test" - "github.com/nspcc-dev/neofs-node/pkg/network" "github.com/stretchr/testify/require" ) @@ -68,14 +68,12 @@ func TestNodeSection(t *testing.T) { ind := 0 - addrs.IterateAddresses(func(addr network.Address) bool { + for addr := range slices.Values(addrs) { require.Equal(t, expectedAddr[ind].str, addr.String()) require.Equal(t, expectedAddr[ind].host, addr.URIAddr()) ind++ - - return false - }) + } require.Equal(t, true, relay) diff --git a/cmd/neofs-node/netmap.go b/cmd/neofs-node/netmap.go index 1bc7912ab6..2c55e77b0b 100644 --- a/cmd/neofs-node/netmap.go +++ b/cmd/neofs-node/netmap.go @@ -144,7 +144,7 @@ func nodeKeyFromNetmap(c *cfg) []byte { func (c *cfg) iterateNetworkAddresses(f func(string) bool) { ni := c.cfgNodeInfo.localInfo - ni.IterateNetworkEndpoints(f) + ni.IterateNetworkEndpoints(func(s string) bool { return !f(s) }) } func (c *cfg) addressNum() int { diff --git a/pkg/core/netmap/nodes.go b/pkg/core/netmap/nodes.go index bccd1444c4..48b9457af1 100644 --- a/pkg/core/netmap/nodes.go +++ b/pkg/core/netmap/nodes.go @@ -1,6 +1,10 @@ package netmap -import "github.com/nspcc-dev/neofs-sdk-go/netmap" +import ( + "slices" + + "github.com/nspcc-dev/neofs-sdk-go/netmap" +) // Node is a named type of netmap.NodeInfo which provides interface needed // in the current repository. Node is expected to be used everywhere instead @@ -17,12 +21,8 @@ func (x Node) PublicKey() []byte { // IterateAddresses iterates over all announced network addresses // and passes them into f. Handler MUST NOT be nil. func (x Node) IterateAddresses(f func(string) bool) { - (netmap.NodeInfo)(x).IterateNetworkEndpoints(f) - for _, addr := range (netmap.NodeInfo)(x).ExternalAddresses() { - if f(addr) { - return - } - } + (netmap.NodeInfo)(x).IterateNetworkEndpoints(func(s string) bool { return !f(s) }) + slices.Values((netmap.NodeInfo)(x).ExternalAddresses())(f) } // NumberOfAddresses returns number of announced network addresses. diff --git a/pkg/innerring/processors/netmap/nodevalidation/availability/validator.go b/pkg/innerring/processors/netmap/nodevalidation/availability/validator.go index 50aaab0e43..bc04266dfb 100644 --- a/pkg/innerring/processors/netmap/nodevalidation/availability/validator.go +++ b/pkg/innerring/processors/netmap/nodevalidation/availability/validator.go @@ -23,33 +23,25 @@ func (v Validator) Verify(nodeInfo netmap.NodeInfo) error { var results []*client.ResEndpointInfo var err error - nodeInfo.IterateNetworkEndpoints(func(s string) bool { + for s := range func(f func(string) bool) { nodeInfo.IterateNetworkEndpoints(func(s string) bool { return !f(s) }) } { var res *client.ResEndpointInfo var c *client.Client c, err = createSDKClient(s) if err != nil { - err = fmt.Errorf("'%s': client creation: %w", s, err) - return true + return fmt.Errorf("'%s': client creation: %w", s, err) } - defer func() { - _ = c.Close() - }() timeoutContext, cancel := context.WithTimeout(context.Background(), pingTimeout) - defer cancel() res, err = c.EndpointInfo(timeoutContext, client.PrmEndpointInfo{}) + cancel() + _ = c.Close() if err != nil { - err = fmt.Errorf("'%s': could not ping node with `EndpointInfo`: %w", s, err) - return true + return fmt.Errorf("'%s': could not ping node with `EndpointInfo`: %w", s, err) } results = append(results, res) - return false - }) - if err != nil { - return err } for _, res := range results { @@ -108,21 +100,14 @@ func compareNodeInfos(niExp, niGot netmap.NodeInfo) error { } expAddrM := make(map[string]struct{}, niExp.NumberOfAttributes()) - niExp.IterateNetworkEndpoints(func(s string) bool { + for s := range func(f func(string) bool) { niExp.IterateNetworkEndpoints(func(s string) bool { return !f(s) }) } { expAddrM[s] = struct{}{} - return false - }) + } - niGot.IterateNetworkEndpoints(func(s string) bool { + for s := range func(f func(string) bool) { niGot.IterateNetworkEndpoints(func(s string) bool { return !f(s) }) } { if _, ok := expAddrM[s]; !ok { - err = fmt.Errorf("got unexpected address: %s", s) - return true + return fmt.Errorf("got unexpected address: %s", s) } - - return false - }) - if err != nil { - return err } return nil diff --git a/pkg/morph/client/netmap/add_peer.go b/pkg/morph/client/netmap/add_peer.go index 76145380d1..ae57c3557e 100644 --- a/pkg/morph/client/netmap/add_peer.go +++ b/pkg/morph/client/netmap/add_peer.go @@ -2,6 +2,7 @@ package netmap import ( "fmt" + "slices" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" netmaprpc "github.com/nspcc-dev/neofs-contract/rpc/netmap" @@ -27,10 +28,7 @@ func (c *Client) AddPeer(ni netmap.NodeInfo, pkey *keys.PublicKey) error { Key: pkey, State: netmaprpc.NodeStateOnline, } - ni.IterateNetworkEndpoints(func(addr string) bool { - node.Addresses = append(node.Addresses, addr) - return false - }) + node.Addresses = slices.Collect(func(f func(s string) bool) { ni.IterateNetworkEndpoints(func(s string) bool { return !f(s) }) }) ni.IterateAttributes(func(k, v string) { node.Attributes[k] = v }) diff --git a/pkg/network/cache/multi.go b/pkg/network/cache/multi.go index 2998cf035d..d423836403 100644 --- a/pkg/network/cache/multi.go +++ b/pkg/network/cache/multi.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "io" + "slices" "sync" "time" @@ -100,10 +101,9 @@ func (x *multiClient) createForAddress(addr network.Address) (clientcore.Client, func (x *multiClient) updateGroup(group network.AddressGroup) { // Firstly, remove old clients. cache := make([]string, 0, group.Len()) - group.IterateAddresses(func(a network.Address) bool { + for a := range slices.Values(group) { cache = append(cache, a.String()) - return false - }) + } x.addrMtx.RLock() oldGroup := x.addr @@ -148,11 +148,12 @@ func (x *multiClient) iterateClients(ctx context.Context, f func(clientcore.Clie group := x.addr x.addrMtx.RUnlock() - group.IterateAddresses(func(addr network.Address) bool { +loop: + for addr := range slices.Values(group) { select { case <-ctx.Done(): firstErr = context.Canceled - return true + break loop default: } @@ -178,8 +179,10 @@ func (x *multiClient) iterateClients(ctx context.Context, f func(clientcore.Clie x.ReportError(err) } - return success - }) + if success { + break + } + } return firstErr } diff --git a/pkg/network/group.go b/pkg/network/group.go index c5aa53eac6..a82eaa0e5d 100644 --- a/pkg/network/group.go +++ b/pkg/network/group.go @@ -21,33 +21,11 @@ type AddressGroup []Address func StringifyGroup(x AddressGroup) string { var s string - iterateAllAddresses(x, func(addr Address) { + for addr := range slices.Values(x) { s += addr.String() - }) - - return s -} - -// IterateAddresses iterates over all network addresses of the node. -// -// Breaks iterating on handler's true return. -// -// Handler should not be nil. -func (x AddressGroup) IterateAddresses(f func(Address) bool) { - for i := range x { - if f(x[i]) { - break - } } -} -// iterateAllAddresses iterates over all network addresses of g -// and passes each of them to f. -func iterateAllAddresses(g AddressGroup, f func(Address)) { - g.IterateAddresses(func(addr Address) bool { - f(addr) - return false - }) + return s } // Len returns number of addresses in AddressGroup. @@ -69,7 +47,7 @@ func (x AddressGroup) Swap(i, j int) { // MultiAddressIterator is an interface of network address group. type MultiAddressIterator interface { // IterateAddresses must iterate over network addresses and pass each one - // to the handler until it returns true. + // to the handler until it returns false. IterateAddresses(func(string) bool) // NumberOfAddresses must return number of addresses in group. @@ -125,22 +103,20 @@ func (x *AddressGroup) FromIterator(iter MultiAddressIterator) error { // iterateParsedAddresses parses each address from MultiAddressIterator and passes it to f // until 1st parsing failure or f's error. -func iterateParsedAddresses(iter MultiAddressIterator, f func(s Address) error) (err error) { - iter.IterateAddresses(func(s string) bool { +func iterateParsedAddresses(iter MultiAddressIterator, f func(s Address) error) error { + for s := range iter.IterateAddresses { var a Address - err = a.FromString(s) + err := a.FromString(s) if err != nil { - err = fmt.Errorf("could not parse address from string: %w", err) - return true + return fmt.Errorf("could not parse address from string: %w", err) } - err = f(a) - - return err != nil - }) - - return + if err = f(a); err != nil { + return err + } + } + return nil } // WriteToNodeInfo writes AddressGroup to netmap.NodeInfo structure. @@ -148,10 +124,10 @@ func WriteToNodeInfo(g AddressGroup, ni *netmap.NodeInfo) { num := g.Len() addrs := make([]string, 0, num) - iterateAllAddresses(g, func(addr Address) { + for addr := range slices.Values(g) { ni.SetNetworkEndpoints() addrs = append(addrs, addr.String()) - }) + } ni.SetNetworkEndpoints(addrs...) } diff --git a/pkg/network/validation.go b/pkg/network/validation.go index 8d818943a4..c59f7dc26d 100644 --- a/pkg/network/validation.go +++ b/pkg/network/validation.go @@ -35,7 +35,7 @@ var ( type NodeEndpointsIterator netmap.NodeInfo func (x NodeEndpointsIterator) IterateAddresses(f func(string) bool) { - (netmap.NodeInfo)(x).IterateNetworkEndpoints(f) + (netmap.NodeInfo)(x).IterateNetworkEndpoints(func(s string) bool { return !f(s) }) } func (x NodeEndpointsIterator) NumberOfAddresses() int { diff --git a/pkg/services/audit/auditor/pop.go b/pkg/services/audit/auditor/pop.go index c96f1929aa..2f03f0432b 100644 --- a/pkg/services/audit/auditor/pop.go +++ b/pkg/services/audit/auditor/pop.go @@ -29,7 +29,7 @@ func (c *Context) buildCoverage() { // and process all placement vectors c.iterateSGMembersPlacementRand(func(id oid.ID, ind int, nodes []netmap.NodeInfo) bool { c.processObjectPlacement(id, nodes, policy.ReplicaNumberByIndex(ind)) - return c.containerCovered() + return !c.containerCovered() }) } @@ -128,7 +128,7 @@ func (c *Context) composePair(id oid.ID, n1, n2 netmap.NodeInfo) { func (c *Context) iterateSGMembersPlacementRand(f func(oid.ID, int, []netmap.NodeInfo) bool) { // iterate over storage groups members for all storage groups (one by one) // with randomly shuffled members - c.iterateSGMembersRand(func(id oid.ID) bool { + for id := range c.iterateSGMembersRand { // build placement vector for the current object nn, err := c.buildPlacement(id) if err != nil { @@ -137,21 +137,19 @@ func (c *Context) iterateSGMembersPlacementRand(f func(oid.ID, int, []netmap.Nod zap.Error(err), ) - return false + continue } for i, nodes := range nn { - if f(id, i, nodes) { - return true + if !f(id, i, nodes) { + return } } - - return false - }) + } } func (c *Context) iterateSGMembersRand(f func(oid.ID) bool) { - c.iterateSGInfo(func(members []oid.ID) bool { + for members := range c.iterateSGInfo { ln := len(members) processed := make(map[uint64]struct{}, ln-1) @@ -160,13 +158,11 @@ func (c *Context) iterateSGMembersRand(f func(oid.ID) bool) { ind := nextRandUint64(uint64(ln), processed) processed[ind] = struct{}{} - if f(members[ind]) { - return true + if !f(members[ind]) { + return } } - - return false - }) + } } func (c *Context) iterateSGInfo(f func([]oid.ID) bool) { @@ -178,7 +174,7 @@ func (c *Context) iterateSGInfo(f func([]oid.ID) bool) { // to be shuffled since it is a Search response // with unpredictable order for i := range c.sgMembersCache { - if f(c.sgMembersCache[i]) { + if !f(c.sgMembersCache[i]) { return } } diff --git a/pkg/services/container/announcement/load/route/deps.go b/pkg/services/container/announcement/load/route/deps.go index 2f5138db28..fbf093e708 100644 --- a/pkg/services/container/announcement/load/route/deps.go +++ b/pkg/services/container/announcement/load/route/deps.go @@ -1,6 +1,7 @@ package loadroute import ( + "github.com/nspcc-dev/neofs-node/pkg/network" loadcontroller "github.com/nspcc-dev/neofs-node/pkg/services/container/announcement/load/controller" "github.com/nspcc-dev/neofs-sdk-go/container" ) @@ -12,13 +13,7 @@ type ServerInfo interface { // from the route in a binary representation. PublicKey() []byte - // IterateAddresses iterates over network addresses of the node - // in the route. Breaks iterating on true return - // of the handler. - IterateAddresses(func(string) bool) - - // NumberOfAddresses returns number of server's network addresses. - NumberOfAddresses() int + network.MultiAddressIterator // ExternalAddresses returns external node's addresses. ExternalAddresses() []string diff --git a/pkg/services/reputation/common/deps.go b/pkg/services/reputation/common/deps.go index f56819d54b..2d1ec6d5a3 100644 --- a/pkg/services/reputation/common/deps.go +++ b/pkg/services/reputation/common/deps.go @@ -4,6 +4,7 @@ import ( "context" "io" + "github.com/nspcc-dev/neofs-node/pkg/network" "github.com/nspcc-dev/neofs-node/pkg/services/reputation" apireputation "github.com/nspcc-dev/neofs-sdk-go/reputation" ) @@ -70,13 +71,7 @@ type ServerInfo interface { // from the route in a binary representation. PublicKey() []byte - // IterateAddresses iterates over network addresses of the node - // in the route. Breaks iterating on true return - // of the handler. - IterateAddresses(func(string) bool) - - // NumberOfAddresses returns number of server's network addresses. - NumberOfAddresses() int + network.MultiAddressIterator // ExternalAddresses returns external addresses of a node. ExternalAddresses() []string diff --git a/pkg/services/reputation/common/managers.go b/pkg/services/reputation/common/managers.go index f595d4eed8..d74ef68a94 100644 --- a/pkg/services/reputation/common/managers.go +++ b/pkg/services/reputation/common/managers.go @@ -62,7 +62,7 @@ func (x nodeServer) PublicKey() []byte { } func (x nodeServer) IterateAddresses(f func(string) bool) { - (apiNetmap.NodeInfo)(x).IterateNetworkEndpoints(f) + (apiNetmap.NodeInfo)(x).IterateNetworkEndpoints(func(s string) bool { return !f(s) }) } func (x nodeServer) NumberOfAddresses() int { diff --git a/pkg/services/tree/redirect.go b/pkg/services/tree/redirect.go index 72c408e6c2..6f84efc9c7 100644 --- a/pkg/services/tree/redirect.go +++ b/pkg/services/tree/redirect.go @@ -22,20 +22,18 @@ func (s *Service) forEachNode(ctx context.Context, cntNodes []netmapSDK.NodeInfo var called bool for _, n := range cntNodes { - var stop bool - n.IterateNetworkEndpoints(func(endpoint string) bool { + for endpoint := range func(f func(string) bool) { n.IterateNetworkEndpoints(func(s string) bool { return !f(s) }) } { c, err := s.cache.get(endpoint) if err != nil { - return false + continue } s.log.Debug("redirecting tree service query", zap.String("endpoint", endpoint)) called = true - stop = f(c) - return true - }) - if stop { - return nil + if f(c) { + return nil + } + break } } if !called { diff --git a/pkg/services/tree/replicator.go b/pkg/services/tree/replicator.go index d7aab6d834..4039e1ca6a 100644 --- a/pkg/services/tree/replicator.go +++ b/pkg/services/tree/replicator.go @@ -62,21 +62,23 @@ func (s *Service) replicationWorker(ctx context.Context) { var lastErr error var lastAddr string - task.n.IterateNetworkEndpoints(func(addr string) bool { + for addr := range func(f func(string) bool) { task.n.IterateNetworkEndpoints(func(s string) bool { return !f(s) }) } { lastAddr = addr c, err := s.cache.get(addr) if err != nil { lastErr = fmt.Errorf("can't create client: %w", err) - return false + continue } ctx, cancel := context.WithTimeout(ctx, s.replicatorTimeout) _, lastErr = c.Apply(ctx, task.req) cancel() - return lastErr == nil - }) + if lastErr == nil { + break + } + } if lastErr != nil { if errors.Is(lastErr, errRecentlyFailed) { diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index 7e320594ad..7c8e06a797 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -146,18 +146,18 @@ func (s *Service) synchronizeTree(ctx context.Context, d pilorama.CIDDescriptor, newHeight := uint64(math.MaxUint64) for _, n := range nodes { height := from - n.IterateNetworkEndpoints(func(addr string) bool { + loop: + for addr := range func(f func(string) bool) { n.IterateNetworkEndpoints(func(s string) bool { return !f(s) }) } { var a network.Address if err := a.FromString(addr); err != nil { - return false + continue } cc, err := grpc.NewClient(a.URIAddr(), grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { // Failed to connect, try the next address. - return false + continue } - defer cc.Close() treeClient := NewTreeServiceClient(cc) for { @@ -166,11 +166,12 @@ func (s *Service) synchronizeTree(ctx context.Context, d pilorama.CIDDescriptor, height = h } if err != nil || h <= height { + _ = cc.Close() // Error with the response, try the next node. - return true + break loop } } - }) + } if height <= from { // do not increase starting height on fail newHeight = from } else if height < newHeight { // take minimum across all clients