package getsvc import ( "context" "slices" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) func (a *assembler) assembleObjectByChildrenListRange(ctx context.Context, childrenIDs []oid.ID, writer ObjectWriter) error { if err := a.assemblePayloadInReverseRange(ctx, writer, childrenIDs[len(childrenIDs)-1]); err != nil { return err } return writer.WriteChunk(ctx, a.parentObject.Payload()) } func (a *assembler) assemleObjectByPreviousIDInReverseRange(ctx context.Context, prevID oid.ID, writer ObjectWriter) error { if err := a.assemblePayloadInReverseRange(ctx, writer, prevID); err != nil { return err } if err := writer.WriteChunk(ctx, a.parentObject.Payload()); err != nil { // last part return err } return nil } func (a *assembler) assemblePayloadByObjectIDsRange(ctx context.Context, writer ObjectWriter, partIDs []oid.ID, partRanges []objectSDK.Range) error { for i := range partIDs { _, err := a.getChildObject(ctx, partIDs[i], &partRanges[i], false, writer) if err != nil { return err } } return nil } func (a *assembler) assemblePayloadInReverseRange(ctx context.Context, writer ObjectWriter, prevID oid.ID) error { chain, rngs, err := a.buildChainRange(ctx, prevID) if err != nil { return err } slices.Reverse(chain) slices.Reverse(rngs) return a.assemblePayloadByObjectIDsRange(ctx, writer, chain, rngs) } func (a *assembler) buildChainRange(ctx context.Context, prevID oid.ID) ([]oid.ID, []objectSDK.Range, error) { var ( chain []oid.ID rngs []objectSDK.Range from = a.rng.GetOffset() to = from + a.rng.GetLength() hasPrev = true ) // fill the chain end-to-start for hasPrev && from < a.currentOffset { head, err := a.objGetter.HeadObject(ctx, prevID) if err != nil { return nil, nil, err } if !a.isChild(head) { return nil, nil, errParentAddressDiffers } nextOffset := a.currentOffset - head.PayloadSize() clampedFrom := max(from, nextOffset) clampedTo := min(to, a.currentOffset) if clampedFrom < clampedTo { index := len(rngs) rngs = append(rngs, objectSDK.Range{}) rngs[index].SetOffset(clampedFrom - nextOffset) rngs[index].SetLength(clampedTo - clampedFrom) id, _ := head.ID() chain = append(chain, id) } a.currentOffset = nextOffset prevID, hasPrev = head.PreviousID() } return chain, rngs, nil }