forked from TrueCloudLab/frostfs-node
104 lines
2.6 KiB
Go
104 lines
2.6 KiB
Go
|
package getsvc
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
|
||
|
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
|
||
|
}
|
||
|
|
||
|
for left, right := 0, len(chain)-1; left < right; left, right = left+1, right-1 {
|
||
|
chain[left], chain[right] = chain[right], chain[left]
|
||
|
rngs[left], rngs[right] = rngs[right], rngs[left]
|
||
|
}
|
||
|
|
||
|
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 {
|
||
|
if a.currentOffset <= from {
|
||
|
break
|
||
|
}
|
||
|
|
||
|
head, err := a.objGetter.HeadObject(ctx, prevID)
|
||
|
if err != nil {
|
||
|
return nil, nil, err
|
||
|
}
|
||
|
if !a.isChild(head) {
|
||
|
return nil, nil, errParentAddressDiffers
|
||
|
}
|
||
|
|
||
|
sz := head.PayloadSize()
|
||
|
|
||
|
a.currentOffset -= sz
|
||
|
|
||
|
if a.currentOffset < to {
|
||
|
off := uint64(0)
|
||
|
if from > a.currentOffset {
|
||
|
off = from - a.currentOffset
|
||
|
sz -= from - a.currentOffset
|
||
|
}
|
||
|
|
||
|
if to < a.currentOffset+off+sz {
|
||
|
sz = to - off - a.currentOffset
|
||
|
}
|
||
|
|
||
|
index := len(rngs)
|
||
|
rngs = append(rngs, objectSDK.Range{})
|
||
|
rngs[index].SetOffset(off)
|
||
|
rngs[index].SetLength(sz)
|
||
|
|
||
|
id, _ := head.ID()
|
||
|
chain = append(chain, id)
|
||
|
}
|
||
|
|
||
|
prevID, hasPrev = head.PreviousID()
|
||
|
}
|
||
|
|
||
|
return chain, rngs, nil
|
||
|
}
|