From 387d1e2977b1c5c5707406e383c2fa337b9e575d Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Sat, 10 Dec 2022 13:50:08 +0300 Subject: [PATCH] [#2127] services/tree: Randomize node order for synchronization Signed-off-by: Evgenii Stratonikov --- CHANGELOG.md | 1 + pkg/services/tree/sync.go | 23 +++++++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d28c64dfe9..995f4941e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ Changelog for NeoFS Node - Allow object removal without linking object (#2100) - `neofs-cli container delete` command pre-checks container ownership (#2106) - Policer cache size is now 1024 (#2158) +- Tree service now synchronizes with container nodes in a random order (#2127) ### Fixed - Open FSTree in sync mode by default (#1992) diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index 04be0ead45..896dea5578 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -6,8 +6,10 @@ import ( "errors" "fmt" "io" + "math/rand" "github.com/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" + "github.com/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "github.com/TrueCloudLab/frostfs-node/pkg/network" cid "github.com/TrueCloudLab/frostfs-sdk-go/container/id" netmapSDK "github.com/TrueCloudLab/frostfs-sdk-go/netmap" @@ -39,7 +41,7 @@ func (s *Service) SynchronizeAllTrees(ctx context.Context, cid cid.ID) error { d.Position = pos d.Size = len(nodes) - nodes = append(nodes[:pos], nodes[pos+1:]...) // exclude that node + nodes = randomizeNodeOrder(nodes, pos) if len(nodes) == 0 { return errNoOtherNodes } @@ -108,7 +110,7 @@ func (s *Service) SynchronizeTree(ctx context.Context, cid cid.ID, treeID string d.Position = pos d.Size = len(nodes) - nodes = append(nodes[:pos], nodes[pos+1:]...) // exclude that node + nodes = randomizeNodeOrder(nodes, pos) if len(nodes) == 0 { return errNoOtherNodes } @@ -310,3 +312,20 @@ func (s *Service) syncLoop(ctx context.Context) { } } } + +// randomizeNodeOrder shuffles nodes and removes not a `pos` index. +// It is assumed that 0 <= pos < len(nodes) +func randomizeNodeOrder(cnrNodes []netmap.NodeInfo, pos int) []netmap.NodeInfo { + if len(cnrNodes) == 1 { + return nil + } + + nodes := make([]netmap.NodeInfo, len(cnrNodes)-1) + n := copy(nodes, cnrNodes[:pos]) + copy(nodes[n:], cnrNodes[pos+1:]) + + rand.Shuffle(len(nodes), func(i, j int) { + nodes[i], nodes[j] = nodes[j], nodes[i] + }) + return nodes +}