From e7925fbc1c584a9886fc9a6685a5080f41e096d8 Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Thu, 17 Sep 2020 18:37:44 +0300 Subject: [PATCH] [#31] placement: Implement container placement traverser Signed-off-by: Leonard Lyubich --- go.mod | 2 +- go.sum | Bin 58116 -> 58361 bytes .../object_manager/placement/netmap.go | 32 +++ .../object_manager/placement/traverser.go | 182 ++++++++++++++++++ .../placement/traverser_test.go | 120 ++++++++++++ 5 files changed, 335 insertions(+), 1 deletion(-) create mode 100644 pkg/services/object_manager/placement/netmap.go create mode 100644 pkg/services/object_manager/placement/traverser.go create mode 100644 pkg/services/object_manager/placement/traverser_test.go diff --git a/go.mod b/go.mod index a38a0750..91d8a572 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/multiformats/go-multiaddr-net v0.1.2 // v0.1.1 => v0.1.2 github.com/multiformats/go-multihash v0.0.13 // indirect github.com/nspcc-dev/neo-go v0.91.1-pre.0.20200827184617-7560aa345a78 - github.com/nspcc-dev/neofs-api-go v1.3.1-0.20200916115135-ff325b877023 + github.com/nspcc-dev/neofs-api-go v1.3.1-0.20200917104527-95ae0a649608 github.com/nspcc-dev/neofs-crypto v0.3.0 github.com/nspcc-dev/tzhash v1.4.0 github.com/panjf2000/ants/v2 v2.3.0 diff --git a/go.sum b/go.sum index 339114a6840df098eb6b576d8a9ae9caea7be979..a05829f296f55a2e1a6b11d1fa21c3ded78c4ca1 100644 GIT binary patch delta 115 zcmZoU#{Ba*^M+&TlReVKoy`pmOiYc;buCR3Qw 0 { + c.rem = v + } + } +} + +// WithoutSuccessTracking disables success tracking in traversal. +func WithoutSuccessTracking() Option { + return func(c *cfg) { + c.rem = -1 + } +} diff --git a/pkg/services/object_manager/placement/traverser_test.go b/pkg/services/object_manager/placement/traverser_test.go new file mode 100644 index 00000000..291ec070 --- /dev/null +++ b/pkg/services/object_manager/placement/traverser_test.go @@ -0,0 +1,120 @@ +package placement + +import ( + "strconv" + "testing" + + "github.com/nspcc-dev/neofs-api-go/pkg/netmap" + "github.com/nspcc-dev/neofs-api-go/pkg/object" + netmapV2 "github.com/nspcc-dev/neofs-node/pkg/morph/client/netmap" + "github.com/stretchr/testify/require" +) + +type testBuilder struct { + vectors []netmap.Nodes +} + +func (b testBuilder) BuildPlacement(*object.Address, *netmap.PlacementPolicy) ([]netmap.Nodes, error) { + return b.vectors, nil +} + +func testNode(v uint32) netmapV2.NodeInfo { + n := netmapV2.NodeInfo{} + n.SetAddress("/ip4/0.0.0.0/tcp/" + strconv.Itoa(int(v))) + + return n +} + +func flattenVectors(vs []netmap.Nodes) netmap.Nodes { + v := make(netmap.Nodes, 0) + + for i := range vs { + v = append(v, vs[i]...) + } + + return v +} + +func testPlacement(t *testing.T, sz []int) []netmap.Nodes { + res := make([]netmap.Nodes, 0, len(sz)) + num := uint32(0) + + for i := range sz { + ns := make([]netmapV2.NodeInfo, 0, sz[i]) + + for j := 0; j < sz[i]; j++ { + ns = append(ns, testNode(num)) + num++ + } + + res = append(res, netmap.NodesFromV2(ns)) + } + + return res +} + +func TestTraverserObjectScenarios(t *testing.T) { + t.Run("search scenario", func(t *testing.T) { + nodes := testPlacement(t, []int{2, 3}) + + allNodes := flattenVectors(nodes) + + tr, err := NewTraverser( + UseBuilder(&testBuilder{vectors: nodes}), + WithoutSuccessTracking(), + ) + require.NoError(t, err) + + require.True(t, tr.Success()) + + for i := range allNodes { + require.Equal(t, allNodes[i].NetworkAddress(), tr.Next().String()) + } + + require.Nil(t, tr.Next()) + require.True(t, tr.Success()) + }) + + t.Run("read scenario", func(t *testing.T) { + nodes := testPlacement(t, []int{5, 3, 4}) + + allNodes := flattenVectors(nodes) + + tr, err := NewTraverser( + UseBuilder(&testBuilder{vectors: nodes}), + ) + require.NoError(t, err) + + for i := range allNodes[:len(allNodes)-3] { + require.Equal(t, allNodes[i].NetworkAddress(), tr.Next().String()) + } + + require.False(t, tr.Success()) + + tr.SubmitSuccess() + + require.True(t, tr.Success()) + + require.Nil(t, tr.Next()) + }) + + t.Run("put scenario", func(t *testing.T) { + nodes := testPlacement(t, []int{3, 3, 3}) + sucCount := 3 + + tr, err := NewTraverser( + UseBuilder(&testBuilder{vectors: nodes}), + SuccessAfter(sucCount), + ) + require.NoError(t, err) + + for i := 0; i < sucCount; i++ { + require.NotNil(t, tr.Next()) + require.False(t, tr.Success()) + tr.SubmitSuccess() + } + + require.Nil(t, tr.Next()) + require.True(t, tr.Success()) + }) +}