diff --git a/pkg/services/object_manager/storagegroup/collect.go b/pkg/services/object_manager/storagegroup/collect.go new file mode 100644 index 0000000000..1a2a6b60d4 --- /dev/null +++ b/pkg/services/object_manager/storagegroup/collect.go @@ -0,0 +1,56 @@ +package storagegroup + +import ( + "github.com/nspcc-dev/neofs-api-go/pkg" + "github.com/nspcc-dev/neofs-api-go/pkg/client" + "github.com/nspcc-dev/neofs-api-go/pkg/container" + objectSDK "github.com/nspcc-dev/neofs-api-go/pkg/object" + "github.com/nspcc-dev/neofs-api-go/pkg/storagegroup" + "github.com/nspcc-dev/neofs-node/pkg/core/object" + objutil "github.com/nspcc-dev/neofs-node/pkg/services/object/util" + "github.com/nspcc-dev/tzhash/tz" +) + +// CollectMembers creates new storage group structure and fills it +// with information about members collected via HeadReceiver. +// +// Resulting storage group consists of physically stored objects only. +func CollectMembers(r objutil.HeadReceiver, cid *container.ID, members []*objectSDK.ID) (*storagegroup.StorageGroup, error) { + var ( + sumPhySize uint64 + phyMembers []*objectSDK.ID + phyHashes [][]byte + addr = objectSDK.NewAddress() + sg = storagegroup.New() + ) + + addr.SetContainerID(cid) + + for i := range members { + addr.SetObjectID(members[i]) + + if err := objutil.IterateAllSplitLeaves(r, addr, func(leaf *object.Object) { + phyMembers = append(phyMembers, leaf.ID()) + sumPhySize += leaf.PayloadSize() + phyHashes = append(phyHashes, leaf.PayloadHomomorphicHash().Sum()) + }); err != nil { + return nil, err + } + } + + sumHash, err := tz.Concat(phyHashes) + if err != nil { + return nil, err + } + + cs := pkg.NewChecksum() + tzHash := [client.TZSize]byte{} + copy(tzHash[:], sumHash) + cs.SetTillichZemor(tzHash) + + sg.SetMembers(phyMembers) + sg.SetValidationDataSize(sumPhySize) + sg.SetValidationDataHash(cs) + + return sg, nil +}