diff --git a/pkg/services/object/util/chain.go b/pkg/services/object/util/chain.go index 52082875bb..b64a456ad2 100644 --- a/pkg/services/object/util/chain.go +++ b/pkg/services/object/util/chain.go @@ -28,14 +28,6 @@ type ObjectSource interface { // Stop boolean result provides the ability to interrupt the traversal. type SplitMemberHandler func(member *object.Object, reverseDirection bool) (stop bool) -// IterateAllSplitLeaves is an iterator over all object split-tree leaves in direct order. -func IterateAllSplitLeaves(r ObjectSource, addr oid.Address, h func(*object.Object)) error { - return IterateSplitLeaves(r, addr, func(leaf *object.Object) bool { - h(leaf) - return false - }) -} - // IterateSplitLeaves is an iterator over object split-tree leaves in direct order. // // If member handler returns true, then the iterator aborts without error. @@ -199,114 +191,3 @@ func headFromReceiver(r ObjectSource, addr oid.Address) (*object.Object, error) return nil, fmt.Errorf("unexpected information: %T", res) } } - -// TraverseSplitChain is an iterator over object split-tree leaves. -// -// Traversal occurs in one of two directions, which depends on what pslit info was received: -// * in direct order for link part; -// * in reverse order for last part. -func TraverseSplitChain(r ObjectSource, addr oid.Address, h SplitMemberHandler) error { - _, err := traverseSplitChain(r, addr, h) - return err -} - -func traverseSplitChain(r ObjectSource, addr oid.Address, h SplitMemberHandler) (bool, error) { - v, err := r.Head(addr) - if err != nil { - return false, err - } - - cnr := addr.Container() - - switch res := v.(type) { - default: - panic(fmt.Sprintf("unexpected result of %T: %T", r, v)) - case *object.Object: - return h(res, false), nil - case *object.SplitInfo: - link := res.GetLink() - last := res.GetLastPart() - - switch { - default: - return false, errors.New("lack of split information") - case !link.IsZero(): - var addr oid.Address - addr.SetContainer(cnr) - addr.SetObject(link) - - chain := make([]oid.ID, 0) - - if _, err := traverseSplitChain(r, addr, func(member *object.Object, reverseDirection bool) (stop bool) { - children := member.Children() - - if reverseDirection { - chain = append(children, chain...) - } else { - chain = append(chain, children...) - } - - return false - }); err != nil { - return false, err - } - - var reverseChain []*object.Object - - for i := range chain { - addr.SetObject(chain[i]) - - if stop, err := traverseSplitChain(r, addr, func(member *object.Object, reverseDirection bool) (stop bool) { - if !reverseDirection { - return h(member, false) - } - - reverseChain = append(reverseChain, member) - return false - }); err != nil || stop { - return stop, err - } - } - - for i := len(reverseChain) - 1; i >= 0; i-- { - if h(reverseChain[i], false) { - return true, nil - } - } - case !last.IsZero(): - var addr oid.Address - addr.SetContainer(cnr) - - for last = res.GetLastPart(); !last.IsZero(); { - addr.SetObject(last) - - var directChain []*object.Object - - if _, err := traverseSplitChain(r, addr, func(member *object.Object, reverseDirection bool) (stop bool) { - if reverseDirection { - last = member.GetPreviousID() - return h(member, true) - } - - directChain = append(directChain, member) - - return false - }); err != nil { - return false, err - } - - for i := len(directChain) - 1; i >= 0; i-- { - if h(directChain[i], true) { - return true, nil - } - } - - if len(directChain) > 0 { - last = directChain[len(directChain)-1].GetPreviousID() - } - } - } - } - - return false, nil -} diff --git a/pkg/services/object/util/placement.go b/pkg/services/object/util/placement.go deleted file mode 100644 index a4fb572f5c..0000000000 --- a/pkg/services/object/util/placement.go +++ /dev/null @@ -1,164 +0,0 @@ -package util - -import ( - "fmt" - - "github.com/nspcc-dev/neofs-node/pkg/core/container" - "github.com/nspcc-dev/neofs-node/pkg/core/netmap" - "github.com/nspcc-dev/neofs-node/pkg/network" - "github.com/nspcc-dev/neofs-node/pkg/services/object_manager/placement" - cid "github.com/nspcc-dev/neofs-sdk-go/container/id" - netmapSDK "github.com/nspcc-dev/neofs-sdk-go/netmap" - oid "github.com/nspcc-dev/neofs-sdk-go/object/id" -) - -type localPlacement struct { - builder placement.Builder - - netmapKeys netmap.AnnouncedKeys -} - -type remotePlacement struct { - builder placement.Builder - - netmapKeys netmap.AnnouncedKeys -} - -// TraverserGenerator represents tool that generates -// container traverser for the particular need. -type TraverserGenerator struct { - netMapSrc netmap.Source - - cnrSrc container.Source - - netmapKeys netmap.AnnouncedKeys - - customOpts []placement.Option -} - -func NewLocalPlacement(b placement.Builder, s netmap.AnnouncedKeys) placement.Builder { - return &localPlacement{ - builder: b, - netmapKeys: s, - } -} - -func (p *localPlacement) BuildPlacement(cnr cid.ID, obj *oid.ID, policy netmapSDK.PlacementPolicy) ([][]netmapSDK.NodeInfo, error) { - vs, err := p.builder.BuildPlacement(cnr, obj, policy) - if err != nil { - return nil, fmt.Errorf("(%T) could not build object placement: %w", p, err) - } - - for i := range vs { - for j := range vs[i] { - var addr network.AddressGroup - - err := addr.FromIterator(network.NodeEndpointsIterator(vs[i][j])) - if err != nil { - continue - } - - if p.netmapKeys.IsLocalKey(vs[i][j].PublicKey()) { - return [][]netmapSDK.NodeInfo{{vs[i][j]}}, nil - } - } - } - - return nil, fmt.Errorf("(%T) local node is outside of object placement", p) -} - -// NewRemotePlacementBuilder creates, initializes and returns placement builder that -// excludes local node from any placement vector. -func NewRemotePlacementBuilder(b placement.Builder, s netmap.AnnouncedKeys) placement.Builder { - return &remotePlacement{ - builder: b, - netmapKeys: s, - } -} - -func (p *remotePlacement) BuildPlacement(cnr cid.ID, obj *oid.ID, policy netmapSDK.PlacementPolicy) ([][]netmapSDK.NodeInfo, error) { - vs, err := p.builder.BuildPlacement(cnr, obj, policy) - if err != nil { - return nil, fmt.Errorf("(%T) could not build object placement: %w", p, err) - } - - for i := range vs { - for j := 0; j < len(vs[i]); j++ { - var addr network.AddressGroup - - err := addr.FromIterator(network.NodeEndpointsIterator(vs[i][j])) - if err != nil { - continue - } - - if p.netmapKeys.IsLocalKey(vs[i][j].PublicKey()) { - vs[i] = append(vs[i][:j], vs[i][j+1:]...) - j-- - } - } - } - - return vs, nil -} - -// NewTraverserGenerator creates, initializes and returns new TraverserGenerator instance. -func NewTraverserGenerator(nmSrc netmap.Source, cnrSrc container.Source, netmapKeys netmap.AnnouncedKeys) *TraverserGenerator { - return &TraverserGenerator{ - netMapSrc: nmSrc, - cnrSrc: cnrSrc, - netmapKeys: netmapKeys, - } -} - -// WithTraverseOptions returns TraverseGenerator that additionally applies provided options. -func (g *TraverserGenerator) WithTraverseOptions(opts ...placement.Option) *TraverserGenerator { - return &TraverserGenerator{ - netMapSrc: g.netMapSrc, - cnrSrc: g.cnrSrc, - netmapKeys: g.netmapKeys, - customOpts: opts, - } -} - -// GenerateTraverser generates placement Traverser for provided object address -// using epoch-th network map. -func (g *TraverserGenerator) GenerateTraverser(idCnr cid.ID, idObj *oid.ID, epoch uint64) (*placement.Traverser, error) { - // get network map by epoch - nm, err := g.netMapSrc.GetNetMapByEpoch(epoch) - if err != nil { - return nil, fmt.Errorf("could not get network map #%d: %w", epoch, err) - } - - // get container related container - cnr, err := g.cnrSrc.Get(idCnr) - if err != nil { - return nil, fmt.Errorf("could not get container: %w", err) - } - - // allocate placement traverser options - traverseOpts := make([]placement.Option, 0, 3+len(g.customOpts)) - traverseOpts = append(traverseOpts, g.customOpts...) - - // create builder of the remote nodes from network map - builder := NewRemotePlacementBuilder( - placement.NewNetworkMapBuilder(nm), - g.netmapKeys, - ) - - traverseOpts = append(traverseOpts, - // set processing container - placement.ForContainer(cnr.Value), - - // set placement builder - placement.UseBuilder(builder), - ) - - if idObj != nil { - traverseOpts = append(traverseOpts, - // set identifier of the processing object - placement.ForObject(*idObj), - ) - } - - return placement.NewTraverser(traverseOpts...) -}