From 21133aee2febdf66323dd5db22b92cc6f81caf57 Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Fri, 29 Jan 2021 03:04:36 +0300 Subject: [PATCH] [#328] container/load: Implement route builder based on placement Implement route Builder interface on wrapper over the container placement builder, Component implies exactly one transfer to each of the most weight nodes of the container (according to some weighing algorithm). Implementation is planned for use when transferring local estimates of storage nodes. Signed-off-by: Leonard Lyubich --- .../load/route/placement/builder.go | 49 +++++++++++++++++++ .../load/route/placement/calls.go | 36 ++++++++++++++ .../announcement/load/route/placement/deps.go | 14 ++++++ 3 files changed, 99 insertions(+) create mode 100644 pkg/services/container/announcement/load/route/placement/builder.go create mode 100644 pkg/services/container/announcement/load/route/placement/calls.go create mode 100644 pkg/services/container/announcement/load/route/placement/deps.go diff --git a/pkg/services/container/announcement/load/route/placement/builder.go b/pkg/services/container/announcement/load/route/placement/builder.go new file mode 100644 index 000000000..061ac5921 --- /dev/null +++ b/pkg/services/container/announcement/load/route/placement/builder.go @@ -0,0 +1,49 @@ +package placementrouter + +import "fmt" + +// Prm groups the required parameters of the Builder's constructor. +// +// All values must comply with the requirements imposed on them. +// Passing incorrect parameter values will result in constructor +// failure (error or panic depending on the implementation). +type Prm struct { + // Calculator of the container members. + // + // Must not be nil. + PlacementBuilder PlacementBuilder +} + +// Builder represents component that routes used container space +// values between nodes from the container. +// +// For correct operation, Builder must be created using +// the constructor (New) based on the required parameters +// and optional components. After successful creation, +// the Builder is immediately ready to work through API. +type Builder struct { + placementBuilder PlacementBuilder +} + +const invalidPrmValFmt = "invalid parameter %s (%T):%v" + +func panicOnPrmValue(n string, v interface{}) { + panic(fmt.Sprintf(invalidPrmValFmt, n, v, v)) +} + +// New creates a new instance of the Builder. +// +// Panics if at least one value of the parameters is invalid. +// +// The created Builder does not require additional +// initialization and is completely ready for work +func New(prm Prm) *Builder { + switch { + case prm.PlacementBuilder == nil: + panicOnPrmValue("RemoteWriterProvider", prm.PlacementBuilder) + } + + return &Builder{ + placementBuilder: prm.PlacementBuilder, + } +} diff --git a/pkg/services/container/announcement/load/route/placement/calls.go b/pkg/services/container/announcement/load/route/placement/calls.go new file mode 100644 index 000000000..61f222d6a --- /dev/null +++ b/pkg/services/container/announcement/load/route/placement/calls.go @@ -0,0 +1,36 @@ +package placementrouter + +import ( + "github.com/nspcc-dev/neofs-api-go/pkg/container" + loadroute "github.com/nspcc-dev/neofs-node/pkg/services/container/announcement/load/route" + "github.com/pkg/errors" +) + +// NextStage composes container nodes for the container and epoch from a, +// and returns the list of nodes with maximum weight (one from each vector). +// +// If passed route has more than one point, then endpoint of the route is reached. +// +// The traversed route is not checked, it is assumed to be correct. +func (b *Builder) NextStage(a container.UsedSpaceAnnouncement, passed []loadroute.ServerInfo) ([]loadroute.ServerInfo, error) { + if len(passed) > 1 { + return nil, nil + } + + placement, err := b.placementBuilder.BuildPlacement(a.Epoch(), a.ContainerID()) + if err != nil { + return nil, errors.Wrapf(err, "could not build placement %s", a.ContainerID()) + } + + res := make([]loadroute.ServerInfo, 0, len(placement)) + + for i := range placement { + if len(placement[i]) == 0 { + continue + } + + res = append(res, placement[i][0]) + } + + return res, nil +} diff --git a/pkg/services/container/announcement/load/route/placement/deps.go b/pkg/services/container/announcement/load/route/placement/deps.go new file mode 100644 index 000000000..ee4397bb3 --- /dev/null +++ b/pkg/services/container/announcement/load/route/placement/deps.go @@ -0,0 +1,14 @@ +package placementrouter + +import ( + "github.com/nspcc-dev/neofs-api-go/pkg/container" + "github.com/nspcc-dev/neofs-api-go/pkg/netmap" +) + +// PlacementBuilder describes interface of NeoFS placement calculator. +type PlacementBuilder interface { + // BuildPlacement must compose and sort (according to a specific algorithm) + // storage nodes from the container with identifier cid using network map + // of particular epoch. + BuildPlacement(epoch uint64, cid *container.ID) ([]netmap.Nodes, error) +}