forked from TrueCloudLab/frostfs-node
87 lines
2.4 KiB
Go
87 lines
2.4 KiB
Go
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
|
|
}
|