diff --git a/cmd/frostfs-cli/modules/object/util.go b/cmd/frostfs-cli/modules/object/util.go index 90b897c1..204409df 100644 --- a/cmd/frostfs-cli/modules/object/util.go +++ b/cmd/frostfs-cli/modules/object/util.go @@ -339,8 +339,6 @@ func initFlagSession(cmd *cobra.Command, verb string) { // container. // // The object itself is not included in the result. -// -// nolint: funlen func collectObjectRelatives(cmd *cobra.Command, cli *client.Client, cnr cid.ID, obj oid.ID) []oid.ID { common.PrintVerbose(cmd, "Fetching raw object header...") @@ -372,13 +370,28 @@ func collectObjectRelatives(cmd *cobra.Command, cli *client.Client, cnr cid.ID, splitInfo := errSplit.SplitInfo() + if members, ok := tryGetSplitMembersByLinkingObject(cmd, splitInfo, prmHead, cnr); ok { + return members + } + + if members, ok := tryGetSplitMembersBySplitID(cmd, splitInfo, cli, cnr); ok { + return members + } + + return tryRestoreChainInReverse(cmd, splitInfo, prmHead, cli, cnr, obj) +} + +func tryGetSplitMembersByLinkingObject(cmd *cobra.Command, splitInfo *object.SplitInfo, prmHead internal.HeadObjectPrm, cnr cid.ID) ([]oid.ID, bool) { // collect split chain by the descending ease of operations (ease is evaluated heuristically). // If any approach fails, we don't try the next since we assume that it will fail too. if idLinking, ok := splitInfo.Link(); ok { common.PrintVerbose(cmd, "Collecting split members using linking object %s...", idLinking) + var addrObj oid.Address + addrObj.SetContainer(cnr) addrObj.SetObject(idLinking) + prmHead.SetAddress(addrObj) prmHead.SetRawFlag(false) // client is already set @@ -390,14 +403,17 @@ func collectObjectRelatives(cmd *cobra.Command, cli *client.Client, cnr cid.ID, common.PrintVerbose(cmd, "Received split members from the linking object: %v", children) // include linking object - return append(children, idLinking) + return append(children, idLinking), true } // linking object is not required for // object collecting common.PrintVerbose(cmd, "failed to get linking object's header: %w", err) } + return nil, false +} +func tryGetSplitMembersBySplitID(cmd *cobra.Command, splitInfo *object.SplitInfo, cli *client.Client, cnr cid.ID) ([]oid.ID, bool) { if idSplit := splitInfo.SplitID(); idSplit != nil { common.PrintVerbose(cmd, "Collecting split members by split ID...") @@ -412,12 +428,18 @@ func collectObjectRelatives(cmd *cobra.Command, cli *client.Client, cnr cid.ID, res, err := internal.SearchObjects(prm) commonCmd.ExitOnErr(cmd, "failed to search objects by split ID: %w", err) - members := res.IDList() + parts := res.IDList() common.PrintVerbose(cmd, "Found objects by split ID: %v", res.IDList()) - return members + return parts, true } + return nil, false +} + +func tryRestoreChainInReverse(cmd *cobra.Command, splitInfo *object.SplitInfo, prmHead internal.HeadObjectPrm, cli *client.Client, cnr cid.ID, obj oid.ID) []oid.ID { + var addrObj oid.Address + addrObj.SetContainer(cnr) idMember, ok := splitInfo.LastPart() if !ok { @@ -427,6 +449,8 @@ func collectObjectRelatives(cmd *cobra.Command, cli *client.Client, cnr cid.ID, common.PrintVerbose(cmd, "Traverse the object split chain in reverse...", idMember) var res *internal.HeadObjectRes + var err error + chain := []oid.ID{idMember} chainSet := map[oid.ID]struct{}{idMember: {}} @@ -437,6 +461,7 @@ func collectObjectRelatives(cmd *cobra.Command, cli *client.Client, cnr cid.ID, common.PrintVerbose(cmd, "Reading previous element of the split chain member %s...", idMember) addrObj.SetObject(idMember) + prmHead.SetAddress(addrObj) res, err = internal.HeadObject(prmHead) commonCmd.ExitOnErr(cmd, "failed to read split chain member's header: %w", err)